#include <amxmodx>
#include <amxmisc>
#include <fakemeta>
#include <engine>
#include <array>
#include <sqlx>
#include <dprp>

// CAPTAIN! WE NEED MORE DILITHIUM CRYSTALS!
#pragma dynamic 32768

#define USER_ITEM_SCAN new Success,First = array_first(g_UserItemArray[id],0,Success); if(array_isfilled(g_UserItemArray[id],First)) for(new Next = First,Num;Next >= 0 && array_isfilled(g_UserItemArray[id],Next);Next = array_next(g_UserItemArray[id],Next,Success,Num))

new g_HudObj

// the handle of the connection tuple
new Handle:g_SqlHandle

// the name of the users table
new const g_UserTable[] = "dprp_users"
// the name of the jobs table
new const g_JobsTable[] = "dprp_jobs"
// the name of the property table
new const g_PropertyTable[] = "dprp_property"
// name of the doors table
new const g_DoorsTable[] = "dprp_doors"
// door keys
new const g_KeysTable[] = "dprp_keys"
// name of the items table
new const g_ItemsTable[] = "dprp_items"
// name of the orgs table
//new const g_OrgsTable[] = "dprp_orgs"

// SQL cvars, serve no purpose other than for other plugins
// in case they want to make their own tuple or something
new const g_HostCvar[] = "dprp_sql_host"
new const g_UserCvar[] = "dprp_sql_user"
new const g_PassCvar[] = "dprp_sql_pass"
new const g_DbCvar[] = "dprp_sql_db"
new const g_TypeCvar[] = "dprp_sql_type"

new g_Host[64]
new g_User[64]
new g_Pass[64]
new g_Db[64]
new g_Type[64]

// amount of jobs currently loaded
new g_JobsNum
// array for jobs
new g_JobsArray
// what the id of each job is
/*new g_JobIds[MAX_JOBS]
// where the jobs names are stored
new g_JobNames[MAX_JOBS][33]
// access of the jobs
new g_JobAccess[MAX_JOBS]
// salary of jobs
new g_JobSalaries[MAX_JOBS]*/

//new g_OrgsNum
//new g_OrgsArray

// rather than making "new Query" every time we use it,
// we'll instead just have one global variable to make
// it a lot faster and less resource consuming.
// this will also act as cache to speed other stuff up
new g_Query[512]

new g_BankMoney[33]
new g_Money[33]
new g_Salary[33]
new g_UserItemArray[33]
new g_UserItemNum[33]
new g_ItemUse[33]
new g_JobId[33]
new g_Hunger[33]
new g_Access[33]
new g_AccessCache[33]
new g_JobRight[33]
new g_BadJob[33]

new p_StartMoney
new p_MoneyOrigin
new p_BankRobTime
new p_BankRobMoney
new p_EdekaRobWait
new p_DinerRobWait
new p_BankRobWait
new p_ItemsPerPage
new p_BankTargetname
new p_EdekaMinPlayers
new p_EdekaMinCops
new p_DinerMinPlayers
new p_DinerMinCops
new p_BankMinPlayers
new p_BankMinCops
new p_SaveTime
new p_Lights
new p_HudTitle
new p_Hostname
new p_HudX[2]
new p_HudY[2]
new p_HudR[2]
new p_HudG[2]
new p_HudB[2]
new p_WalletDeath
new p_RobHud
new p_AuxType
new p_AuxX
new p_AuxY
new p_AuxR
new p_AuxG
new p_AuxB

new g_Time

new g_ItemsArray
new g_ItemsNum

new g_GotInfo[33]
/*
new g_ItemsNames[MAX_ITEMS][33]
new g_ItemsIds[MAX_ITEMS]
new g_ItemsPlugin[MAX_ITEMS]
new g_ItemsHandler[MAX_ITEMS][33]
new g_ItemsDisposable[MAX_ITEMS]
new g_ItemsDescription[MAX_ITEMS][64]
*/

new g_NpcClassname[] = "dprp_npc"
new g_NpcZoneClassname[] = "dprp_zone"

new g_CommandNum
new g_CommandArray
//new g_CommandNames[MAX_COMMANDS][33]
//new g_CommandDescriptions[MAX_COMMANDS][64]

new g_RegisterItem

new g_MenuPage[33]
new g_CurItem[33]
new g_Keys = MENU_KEY_0|MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_4|MENU_KEY_5|MENU_KEY_6|MENU_KEY_7|MENU_KEY_8|MENU_KEY_9
new g_ItemsMenu[] = "DPRP_ItemsMenu"
new g_ItemsDrop[] = "DPRP_ItemsDrop"
new g_ItemsGive[] = "DPRP_ItemsGive"
new g_ItemsOptions[] = "DPRP_ItemsOptions"

new g_ItemClassname[] = "dprp_item"
new g_ItemModel[] = "models/hwrp/w_backpack.mdl"

new g_PropertyArray
new g_PropertyNum

new g_DoorArray
new g_DoorNum

new g_HudPending
// crude hack to make up for 2
new g_HudItems[33 * HUD_NUM][MAX_HUD_ITEMS][64]
new g_HudNum[33][2]
new g_HudObjects[2]

new Float:g_RobOrigin[33][3]

new g_RobInfo[33][5]

new g_EdekaRobber
new g_DinerRobber
new g_BankRobber

new g_BagEnts[2]
new Float:g_BagOrigin[2][3]

new g_LastEdekaRob
new g_LastDinerRob
new g_LastBankRob

new g_BankMoneyTaken

new g_Joined[33]

new g_FillModel[] = "models/pellet.mdl"

new g_ConfigsDir[128]

new g_Version[] = "1.0bRC5"

public plugin_init()
{	
	register_plugin("DeepPurpleRP",g_Version,"Hawk552")
	register_cvar("dprp_version",g_Version,FCVAR_SERVER)
	
	register_menucmd(register_menuid(g_ItemsMenu),g_Keys,"ItemsHandle")
	register_menucmd(register_menuid(g_ItemsOptions),g_Keys,"ItemsOptions")
	register_menucmd(register_menuid(g_ItemsDrop),g_Keys,"ItemsDrop")
	register_menucmd(register_menuid(g_ItemsGive),g_Keys,"ItemsGive")
	
	new ConfigsDir[128]
	get_configsdir(ConfigsDir,127)
	server_cmd("exec %s/dprp.cfg",ConfigsDir)
	
	// I don't like doing this, but since TSRP generally
	// has too many ents, I'm going to avoid spawning an
	// ent and making it think every second.
	// This will also calculate time.
	set_task(1.0,"ShowHud",_,_,_,"b")
	set_task(get_pcvar_float(p_SaveTime),"SaveData")
	
	register_event("DeathMsg","EventDeathMsg","a")
	register_event("ResetHUD","EventResetHUD","b")
	
	register_forward(FM_Sys_Error,"plugin_end")
	
	DPRP_RegisterCmd("say /buy","CmdBuy","Allows you to buy properties you're looking at")
	DPRP_RegisterCmd("say /items","CmdItems","Shows your items and allows you to control them")
	DPRP_RegisterCmd("dprp_joblist","CmdJobList","Shows jobs list")
	DPRP_RegisterCmd("dprp_itemlist","CmdItemList","Shows item list")
	DPRP_RegisterCmd("dprp_help","CmdHelp","Shows command list")
	
	register_forward(DLLFunc_Touch,"ForwardTouch")
	
	g_HudObj = CreateHudSyncObj()
	for(new Count;Count < HUD_NUM;Count++)
		g_HudObjects[Count] = CreateHudSyncObj()
	
	//register_clcmd("amx_employ","CmdEmploy")
	//register_clcmd("amx_setwallet","CmdSetWallet")
	//register_clcmd("amx_setbank","CmdSetBank")
	//register_clcmd("amx_setjob","CmdSetJob")
	
	//register_touch(g_ItemClassname,"player","TouchItem")
	//register_touch("player",g_ItemClassname,"TouchItem2")
}

public client_kill(id)
{
	client_print(id,print_console,"You cannot commit suicide in this server.")
	return PLUGIN_HANDLED
}

public SaveData()
{
	new Players[32],Playersnum
	get_players(Players,Playersnum)
	
	for(new Count;Count < Playersnum;Count++)
		if(g_GotInfo[Players[Count]])
			SaveUserData(Players[Count])
	
	new InternalName[64],ExternalName[64],OwnerName[33],OwnerAuthid[36],Price,Locked,AccessStr[JOB_ACCESSES + 1],Access,Profit,Array,MapName[33],Targetname[33],EntID
	get_mapname(MapName,32)
	
	for(new Count;Count < g_PropertyNum;Count++)
	{		
		Array = array_get_int(g_PropertyArray,Count)
		
		array_get_string(Array,0,InternalName,63)
		array_get_string(Array,1,ExternalName,63)
		array_get_string(Array,2,OwnerName,32)
		array_get_string(Array,3,OwnerAuthid,32)
		Price = array_get_int(Array,4,Price)
		Locked = array_get_int(Array,5,Locked)
		Access = array_get_int(Array,6,Access)
		Profit = array_get_int(Array,7,Profit)	
		
		replace_all(ExternalName,32,"'","\'")
		replace_all(OwnerName,32,"'","\'")
		
		DPRP_IntToAccess(Access,AccessStr,JOB_ACCESSES)
		
		format(g_Query,511,"INSERT INTO %s VALUES ('%s','%s','%s','%s','%d','%d','%s','%d','%s') ON DUPLICATE KEY UPDATE externalname='%s',ownername='%s',ownerauth='%s',price='%d',locked='%d',access='%s',profit='%d'",g_PropertyTable,InternalName,ExternalName,OwnerName,OwnerAuthid,Price,Locked,AccessStr,Profit,MapName,ExternalName,OwnerName,OwnerAuthid,Price,Locked,AccessStr,Profit)
		SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
	}
	
	for(new Count;Count < g_DoorNum;Count++)
	{
		Array = array_get_int(g_DoorArray,Count)
		
		array_get_string(Array,0,Targetname,32)
		EntID = array_get_int(Array,1)
		array_get_string(Array,2,InternalName,32)
		
		if(EntID)
			num_to_str(EntID,Targetname,32)
		
		format(g_Query,511,"INSERT INTO %s VALUES ('%s','%s','%s') ON DUPLICATE KEY UPDATE internalname='%s'",g_DoorsTable,Targetname,InternalName,MapName,InternalName)
		SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
	}
	
	set_task(get_pcvar_float(p_SaveTime),"SaveData")
}

SaveUserItems(id)
{
	new Authid[36],ItemId,ItemName[33]
	
	get_user_authid(id,Authid,35)
	
	USER_ITEM_SCAN
	{
		ItemId = Next
		
		UTIL_DPRP_GetItemName(ItemId,ItemName,32)
		
		Num = array_get_int(g_UserItemArray[id],ItemId)
		if(Num < 1)
			continue
		
		//format(g_Query,511,"IF EXISTS (SELECT * FROM %s WHERE authid='%s' AND itemid='%d')^nUPDATE %s SET num='%d' WHERE authid='%s' AND itemid='%d'^nELSE^nINSERT INTO %s VALUES('%s','%d','%d')",g_ItemsTable,Authid,ItemId,g_ItemsTable,Num,Authid,ItemId,g_ItemsTable,Authid,ItemId,Num)
		format(g_Query,511,"INSERT INTO %s VALUES('%s|%s','%d') ON duplicate KEY UPDATE num='%d'",g_ItemsTable,Authid,ItemName,Num,Num)
		SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
		
		//format(g_Query,511,"SELECT * FROM %s WHERE authid='%s' AND itemid='%d'",g_ItemsTable,Authid,ItemId)
		//SQL_ThreadQuery(g_SqlHandle,"SaveClientItems",g_Query,Data,3)
		//Id = array_get_int(array_get_int(g_UserItemArray[id],Count + 1),1)
		//Num = array_get_int(array_get_int(g_UserItemArray[id],Count + 1),2)
		
		//if(Id && Num)
		//	Pos += format(Items[Pos],511,"%d|%d ",Id,Num)
	}
}

public plugin_precache()
{
	p_StartMoney = register_cvar("dprp_startmoney","500")
	p_BankRobTime = register_cvar("dprp_bank_robtime","120")
	p_MoneyOrigin = register_cvar("dprp_bank_moneybag_end","0 0 0")
	register_cvar("dprp_bank_moneybag_start","0 0 0")
	p_BankRobMoney = register_cvar("dprp_bank_robmoney","7500")
	p_EdekaRobWait = register_cvar("dprp_edeka_robwait","360")
	p_DinerRobWait = register_cvar("dprp_diner_robwait","360")
	p_BankRobWait = register_cvar("dprp_bank_robwait","360")
	p_ItemsPerPage = register_cvar("dprp_items_per_page","30")
	p_BankTargetname = register_cvar("dprp_bank_targetname","BANK")
	p_EdekaMinPlayers = register_cvar("dprp_edeka_rob_minplayers","3")
	p_EdekaMinCops = register_cvar("dprp_edeka_rob_mincops","1")
	p_DinerMinPlayers = register_cvar("dprp_diner_rob_minplayers","3")
	p_DinerMinCops = register_cvar("dprp_diner_rob_mincops","1")
	p_BankMinPlayers = register_cvar("dprp_bank_rob_minplayers","5")
	p_BankMinCops = register_cvar("dprp_bank_rob_mincops","3")
	p_SaveTime = register_cvar("dprp_save_interval","30")
	p_Lights = register_cvar("dprp_lights","q")
	p_HudTitle = register_cvar("dprp_hud_title","#hostname#")
	p_HudX[0] = register_cvar("dprp_hud1_x","-0.8")
	p_HudY[0] = register_cvar("dprp_hud1_y","0.1")
	p_HudR[0] = register_cvar("dprp_hud1_r","0")
	p_HudG[0] = register_cvar("dprp_hud1_g","0")
	p_HudB[0] = register_cvar("dprp_hud1_b","255")
	p_HudX[1] = register_cvar("dprp_hud2_x","0.8")
	p_HudY[1] = register_cvar("dprp_hud2_y","0.1")
	p_HudR[1] = register_cvar("dprp_hud2_r","0")
	p_HudG[1] = register_cvar("dprp_hud2_g","0")
	p_HudB[1] = register_cvar("dprp_hud2_b","255")
	p_RobHud = register_cvar("dprp_rob_hudmessage","2")
	p_Hostname = get_cvar_pointer("hostname")
	p_WalletDeath = register_cvar("dprp_wallet_death","1")
	p_AuxType = register_cvar("dprp_auxhud_type","2")
	p_AuxX = register_cvar("dprp_auxhud_x","0.4")
	p_AuxY = register_cvar("dprp_auxhud_y","0.7")
	p_AuxR = register_cvar("dprp_auxhud_r","255")
	p_AuxG = register_cvar("dprp_auxhud_g","0")
	p_AuxB = register_cvar("dprp_auxhud_b","0")
	
	register_cvar(g_HostCvar,"")
	register_cvar(g_UserCvar,"")
	register_cvar(g_PassCvar,"")
	register_cvar(g_DbCvar,"")
	register_cvar(g_TypeCvar,"")
	
	register_cvar(g_PoliceAccessCvar,"a")
	register_cvar(g_MedicalAccessCvar,"b")
	register_cvar(g_AdminAccessCvar,"z")
	
	new MapName[33],ConfigFile[128],Left[128],Right[128]
	
	get_configsdir(ConfigFile,127)
	add(ConfigFile,127,"/dprp.ini")
	
	new File = fopen(ConfigFile,"r")
	if(!File)
	{
		format(g_Query,511,"Could not open core config file (%s).",ConfigFile)
		UTIL_DPRP_ThrowError(0,1,g_Query,0)
		return
	}
	
	while(!feof(File))
	{
		// bad naming application, but whatever
		fgets(File,ConfigFile,sizeof ConfigFile - 1)
		trim(ConfigFile)
		
		if(ConfigFile[0] == ';')
			continue
		
		parse(ConfigFile,Left,sizeof Left - 1,Right,sizeof Right - 1)
		remove_quotes(Left)
		trim(Left)
		remove_quotes(Right)
		trim(Right)
		
		if(Left[0] && Right[0] && equali(Left,g_HostCvar))
		{
			set_cvar_string(g_HostCvar,Right)
			copy(g_Host,sizeof g_Host - 1,Right)
		}
		else if(Left[0] && Right[0] && equali(Left,g_UserCvar))
		{
			set_cvar_string(g_UserCvar,Right)
			copy(g_User,sizeof g_User - 1,Right)
		}
		else if(Left[0] && Right[0] && equali(Left,g_PassCvar))
		{
			set_cvar_string(g_PassCvar,Right)
			copy(g_Pass,sizeof g_Pass - 1,Right)
		}
		else if(Left[0] && Right[0] && equali(Left,g_DbCvar))
		{
			set_cvar_string(g_DbCvar,Right)
			copy(g_Db,sizeof g_Db - 1,Right)
		}
		else if(Left[0] && Right[0] && equali(Left,g_TypeCvar))
		{
			set_cvar_string(g_TypeCvar,Right)
			copy(g_Type,sizeof g_Type - 1,Right)
		}
	}
	
	fclose(File)
	
	get_mapname(MapName,sizeof MapName - 1)
	get_configsdir(g_Query,sizeof g_Query - 1)
	format(g_ConfigsDir,sizeof g_ConfigsDir - 1,"%s/dprp/%s",g_Query,MapName)
	
	if(!dir_exists(g_ConfigsDir))
	{
		format(g_Query,sizeof g_Query - 1,"Configuration directory missing: %s",g_ConfigsDir)
		UTIL_DPRP_ThrowError(0,1,g_Query,0)
		return
	}
	
	precache_model(g_FillModel)

	if(file_exists(g_ItemModel))
		precache_model(g_ItemModel)
	else
	{
		format(g_Query,sizeof g_Query - 1,"Item model missing: %s",g_ItemModel)
		UTIL_DPRP_ThrowError(0,1,g_Query,0)
		return
	}
	
	g_ItemsArray = array_create()
	
	for(new Count;Count < 33;Count++)
		g_UserItemArray[Count] = array_create()
	
	g_JobsArray = array_create()
	g_CommandArray = array_create()
	g_PropertyArray = array_create()
	g_DoorArray = array_create()
	
	g_RegisterItem = 1
	
	new Forward = CreateMultiForward("DPRP_RegisterItems",ET_IGNORE),Return
	if(!Forward || !ExecuteForward(Forward,Return))
		UTIL_DPRP_ThrowError(0,1,"Could not execute ^"DPRP_RegisterItems^" forward.",0)
		
	g_RegisterItem = 0
	
	SqlInit()
}

public SqlInit()
{
	new Type[64]
	SQL_GetAffinity(Type,sizeof Type - 1)
	
	if(!equali(Type,g_Type) && !SQL_SetAffinity(g_Type))
	{
		format(g_Query,sizeof g_Query - 1,"Failed to set SQL affinity from %s to %s.",Type,g_Type)
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	
	g_SqlHandle = SQL_MakeDbTuple(g_Host,g_User,g_Pass,g_Db)
	if(!g_SqlHandle || g_SqlHandle == Empty_Handle)
	{
		format(g_Query,511,"Failed to create SQL tuple.",Type,g_Type)
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	
	// one of the problems with the original harbu was authid not
	// being 36 max chars. the max is really 36, not 32.
	format(g_Query,511,"CREATE TABLE IF NOT EXISTS %s (authid VARCHAR(36),bankmoney INT(11),wallet INT(11),jobname VARCHAR(36),hunger INT(11),access VARCHAR(27),jobright VARCHAR(27))",g_UserTable)
	SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
	
	format(g_Query,511,"CREATE TABLE IF NOT EXISTS %s (name VARCHAR(32),salary INT(11),access VARCHAR(27))",g_JobsTable)
	SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
	
	format(g_Query,511,"CREATE TABLE IF NOT EXISTS %s (internalname VARCHAR(66),externalname VARCHAR(66),ownername VARCHAR(40),ownerauth VARCHAR(36),price INT(11),locked INT(11),access VARCHAR(27),profit INT(11),mapname VARCHAR(36),UNIQUE KEY (internalname))",g_PropertyTable)
	SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
	
	format(g_Query,511,"CREATE TABLE IF NOT EXISTS %s (targetname VARCHAR(36),internalname VARCHAR(66),mapname VARCHAR(36),UNIQUE KEY (targetname))",g_DoorsTable)
	SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
	
	format(g_Query,511,"CREATE TABLE IF NOT EXISTS %s (authid VARCHAR(36),internalname VARCHAR (36),mapname VARCHAR(36))",g_KeysTable)
	SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
	
	format(g_Query,511,"CREATE TABLE IF NOT EXISTS %s (authidname VARCHAR(64),num INT(11),UNIQUE KEY (authidname))",g_ItemsTable)
	SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
	
	format(g_Query,511,"SELECT * FROM %s",g_JobsTable)
	SQL_ThreadQuery(g_SqlHandle,"FetchJobs",g_Query)
	
	format(g_Query,511,"SELECT * FROM %s",g_PropertyTable)
	SQL_ThreadQuery(g_SqlHandle,"FetchProperties",g_Query)
	
	format(g_Query,511,"SELECT * FROM %s",g_DoorsTable)
	SQL_ThreadQuery(g_SqlHandle,"FetchDoors",g_Query)

	set_task(0.1,"CheckMoneyBags")
	
	new Forward = CreateMultiForward("DPRP_Init",ET_IGNORE),Return
	if(Forward <= 0 || !ExecuteForward(Forward,Return))
	{
		format(g_Query,511,"Could not create DPRP_Init forward.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	
	return DestroyForward(Forward)
}

public CheckMoneyBags()
{
	new Float:Origin[3],StrTemp[24],TempOrigins[3][6]
	get_cvar_string("dprp_bank_moneybag_start",StrTemp,23)
	
	parse(StrTemp,TempOrigins[0],5,TempOrigins[1],5,TempOrigins[2],5)
	
	for(new Count;Count < 3;Count++)
		Origin[Count] = str_to_float(TempOrigins[Count])
	
	find_sphere_class(0,"func_pushable",250.0,g_BagEnts,2,Origin)
	
	if(!g_BagEnts[0] || !g_BagEnts[1])
	{
		format(g_Query,511,"Money bags not found in relation to origin given; look in dprp.cfg.")
		UTIL_DPRP_ThrowError(0,0,g_Query,0)
	}
	else
	{
		entity_get_vector(g_BagEnts[0],EV_VEC_origin,g_BagOrigin[0])
		entity_get_vector(g_BagEnts[1],EV_VEC_origin,g_BagOrigin[1])
	}	
}

public FetchProperties(FailState,Handle:Query,Error[],Errcode,Data[],DataSize)
{
	if(FailState == TQUERY_CONNECT_FAILED)
	{
		format(g_Query,511,"Could not connect to SQL database.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	else if(FailState == TQUERY_QUERY_FAILED)
	{
		format(g_Query,511,"Internal error: consult developer.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	
	if(Errcode)
	{
		format(g_Query,511,"Error on query: %s",Error)
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	
	new InternalName[64],ExternalName[64],OwnerName[33],OwnerAuthid[36],Price,Locked,AccessStr[JOB_ACCESSES + 1],Access,Profit,Mapname[33],CurrentMap[33]
	get_mapname(CurrentMap,32)
	
	while(SQL_MoreResults(Query))
	{
		SQL_ReadResult(Query,8,Mapname,32)
		if(!equali(Mapname,CurrentMap))
		{
			SQL_NextRow(Query)
			continue
		}
		
		SQL_ReadResult(Query,0,InternalName,63)
		SQL_ReadResult(Query,1,ExternalName,63)
		SQL_ReadResult(Query,2,OwnerName,32)
		SQL_ReadResult(Query,3,OwnerAuthid,35)
		Price = SQL_ReadResult(Query,4)
		Locked = SQL_ReadResult(Query,5)
		SQL_ReadResult(Query,6,AccessStr,JOB_ACCESSES)
		Access = DPRP_AccessToInt(AccessStr)
		Profit = SQL_ReadResult(Query,7)
		
		new Array = array_create()
		array_set_int(g_PropertyArray,g_PropertyNum++,Array)
		
		array_set_string(Array,0,InternalName)
		array_set_string(Array,1,ExternalName)
		array_set_string(Array,2,OwnerName)
		array_set_string(Array,3,OwnerAuthid)
		array_set_int(Array,4,Price)
		array_set_int(Array,5,Locked)
		array_set_int(Array,6,Access)
		array_set_int(Array,7,Profit)	
		array_set_int(Array,8,0)
		
		SQL_NextRow(Query)
	}
	
	return PLUGIN_CONTINUE
}

public FetchDoors(FailState,Handle:Query,Error[],Errcode,Data[],DataSize)
{
	if(FailState == TQUERY_CONNECT_FAILED)
	{
		format(g_Query,511,"Could not connect to SQL database.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	else if(FailState == TQUERY_QUERY_FAILED)
	{
		format(g_Query,511,"Internal error: consult developer.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	
	if(Errcode)
	{
		format(g_Query,511,"Error on query: %s",Error)
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	
	new Targetname[64],InternalName[64],Mapname[33],CurrentMap[33]
	get_mapname(CurrentMap,32)
	while(SQL_MoreResults(Query))
	{
		SQL_ReadResult(Query,2,Mapname,32)
		if(!equali(Mapname,CurrentMap))
		{
			SQL_NextRow(Query)
			continue
		}
		
		SQL_ReadResult(Query,0,Targetname,63)
		SQL_ReadResult(Query,1,InternalName,63)
		
		new Array = array_create(),Mode = is_str_num(Targetname)
		array_set_int(g_DoorArray,g_DoorNum++,Array)
		
		array_set_string(Array,0,Mode ? "" : Targetname)
		array_set_int(Array,1,Mode ? str_to_num(Targetname) : 0)	
		array_set_string(Array,2,InternalName)
		
		SQL_NextRow(Query)
	}
	
	return PLUGIN_CONTINUE
}

public FetchJobs(FailState,Handle:Query,Error[],Errcode,Data[],DataSize)
{
	if(FailState == TQUERY_CONNECT_FAILED)
	{
		format(g_Query,511,"Could not connect to SQL database.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	else if(FailState == TQUERY_QUERY_FAILED)
	{
		format(g_Query,511,"Internal error: consult developer.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	
	if(Errcode)
	{
		format(g_Query,511,"Error on query: %s",Error)
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
		
	new Temp[JOB_ACCESSES + 1],Array
	while(SQL_MoreResults(Query))
	{
		Array = array_create()
		array_set_int(g_JobsArray,g_JobsNum++,Array)
		
		SQL_ReadResult(Query,0,g_Query,511)
		array_set_string(Array,1,g_Query)
		
		array_set_int(Array,2,SQL_ReadResult(Query,1))
		
		SQL_ReadResult(Query,2,Temp,JOB_ACCESSES)
		array_set_int(Array,3,DPRP_AccessToInt(Temp))
		
		SQL_NextRow(Query)
	}
	
	return PLUGIN_CONTINUE
}

public plugin_end()
{
	SaveData()
	
	array_destroy(g_ItemsArray)
	
	for(new Count;Count < 33;Count++)		
		array_destroy(g_UserItemArray[Count])
	
	new Num
	
	for(new Count;Count < g_CommandNum;Count++)
	{
		Num = array_get_int(g_CommandArray,Count + 1)
		array_destroy(Num)
	}
	
	for(new Count;Count < g_JobsNum;Count++)
	{
		Num = array_get_int(g_JobsArray,Count)
		array_destroy(Num)
	}
	
	for(new Count;Count < g_PropertyNum;Count++)
	{
		Num = array_get_int(g_PropertyArray,Count)
		array_destroy(Num)
	}
	
	for(new Count;Count < g_DoorNum;Count++)
	{
		Num = array_get_int(g_DoorArray,Count)
		array_destroy(Num)
	}
	
	array_destroy(g_JobsArray)
	array_destroy(g_PropertyArray)
	array_destroy(g_CommandArray)
	array_destroy(g_DoorArray)
		
	SQL_FreeHandle(g_SqlHandle)
}
		
public client_disconnect(id)
{	
	if(g_GotInfo[id])
		SaveUserData(id)
		
	for(new Count,Array;Count < g_PropertyNum;Count++)
	{
		Array = array_get_int(g_PropertyArray,Count)
		if(array_get_int(Array,8) & (1<<id))
			array_set_int(Array,8,array_get_int(Array,8) - (1<<id))
	}
	
	g_UserItemNum[id] = 0
	
	g_BadJob[id] = 0
	
	array_clear(g_UserItemArray[id])
}

public SaveUserData(id)
{
	SaveUserItems(id)
	
	new Access[27],JobRight[27],Authid[36],JobName[33]
	DPRP_IntToAccess(g_AccessCache[id],Access,26)
	DPRP_IntToAccess(g_JobRight[id],JobRight,26)
	array_get_string(array_get_int(g_JobsArray,g_JobId[id]),1,JobName,32)
	
	get_user_authid(id,Authid,35)
	
	format(g_Query,511,"UPDATE %s SET bankmoney='%d',wallet='%d',jobname='%s',hunger='%d',access='%s',jobright='%s' WHERE authid='%s'",g_UserTable,g_BankMoney[id],g_Money[id],JobName,g_Hunger[id],Access,JobRight,Authid)
	SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
}

public CmdHelp(id)
{
	new Arg[33]
	read_argv(1,Arg,32)
	
	new Start = str_to_num(Arg),Items = get_pcvar_num(p_ItemsPerPage)
	
	if(Start >= g_CommandNum || Start < 0)
	{
		client_print(id,print_console,"No help items to display at this area.")
		return PLUGIN_HANDLED
	}
	
	client_print(id,print_console,"DPRP Help List (Starting at #%d)",Start)
	client_print(id,print_console,"NUMBER   COMMAND   DESCRIPTION")
	
	for(new Count = Start;Count < Start + Items;Count++)
	{
		if(Count >= g_CommandNum)
			break
		
		array_get_string(array_get_int(g_CommandArray,Count + 1),1,Arg,32)
		array_get_string(array_get_int(g_CommandArray,Count + 1),2,g_Query,511)
		
		client_print(id,print_console,"#%d   %s   %s",Count + 1,Arg,g_Query)
	}
	
	if(Start + Items < g_CommandNum)
		client_print(id,print_console,"Type ^"dprp_help %d^" to view next items.",Start + Items)
	
	return PLUGIN_HANDLED
}

public CmdBuy(id)
{
	new Index,Body
	get_user_aiming(id,Index,Body,100)
	
	if(Index)
	{
		new Targetname[33],Return
		entity_get_string(Index,EV_SZ_targetname,Targetname,32)
		
		new Classname[33]
		entity_get_string(Index,EV_SZ_classname,Classname,32)
		
		new Property = UTIL_DPRP_GetProperty(Targetname,Index)
		if(Property == -1)
			return PLUGIN_HANDLED
		
		//if((equal(Classname,"func_door") || equal(Classname,"func_door_rotating")) && entity_get_int(Index,EV_INT_bInDuck))
		//	DPRP_RealProperty(Index,Targetname,Targetname,32)
		//else
		//	return PLUGIN_HANDLED
		
		new Array = array_get_int(g_PropertyArray,Property),Price = array_get_int(Array,4),Authid[36],EntAuthid[36]
		
		get_user_authid(id,Authid,35)
		array_get_string(Array,3,EntAuthid,35)
		
		if(Price && g_BankMoney[id] >= Price && !equali(Authid,EntAuthid))
		{
			new Forward = CreateMultiForward("DPRP_BuyProperty",ET_STOP2,FP_CELL,FP_CELL)
			if(Forward < 0)
			{
				format(g_Query,511,"Could not create DPRP_BuyProperty forward.")
				return UTIL_DPRP_ThrowError(0,1,g_Query,0)
			}
			
			if(!ExecuteForward(Forward,Return,id,Property + 1))
			{
				format(g_Query,511,"Could not execute DPRP_BuyProperty forward.")
				return UTIL_DPRP_ThrowError(0,1,g_Query,0)
			}
			
			DestroyForward(Forward)
			
			if(!Return)
			{
				g_BankMoney[id] -= Price
				
				new Name[33]
				get_user_name(id,Name,32)
				
				array_set_string(Array,2,Name)
				array_set_string(Array,3,Authid)
				array_set_int(Array,4,0) 
				array_set_int(Array,8,0)
				
				new InternalName[64]
				array_get_string(Array,0,InternalName,63)
				
				format(g_Query,511,"DELETE FROM %s WHERE internalname='%s'",g_KeysTable,InternalName)
				SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
			}
		}
	}
		
	return PLUGIN_HANDLED
}

public CmdItems(id)
{
	g_MenuPage[id] = 0
	ShowItems(id)
	
	return PLUGIN_HANDLED
}

ShowItems(id)
{	
	if(!is_user_alive(id))
		return PLUGIN_HANDLED
		
	new Menu[512],Pos,Len = sizeof Menu - 1,MenuOptions = 7,Start = g_MenuPage[id] * MenuOptions,ItemName[33]
	
	Pos += format(Menu[Pos],Len - Pos,"DeepPurpleRP Items^n^n")
	
	new Success,Last = array_last(g_UserItemArray[id],-1,Success),ItemId,Num = Start,MenuItemNum,Keys = MENU_KEY_0|MENU_KEY_8|MENU_KEY_9
	if(!Success && !array_isfilled(g_UserItemArray[id],Last))
	{
		client_print(id,print_chat,"[DPRP] You have no items in your inventory.")
		return PLUGIN_HANDLED
	}
	
	while(Num < Start + MenuOptions && (ItemId = array_get_nth(g_UserItemArray[id],++Num,_,Success)) != -1)
	{
		if(!array_isfilled(g_UserItemArray[id],ItemId))
			break
		
		Keys |= (1<<MenuItemNum)
		
		UTIL_DPRP_ValidItemId(ItemId) ? UTIL_DPRP_GetItemName(ItemId,ItemName,32) : copy(ItemName,32,"BAD ITEMID: Contact admin")
		Pos += format(Menu[Pos],Len - Pos,"%d. %s x %d^n",++MenuItemNum,ItemName,UTIL_DPRP_GetUserItemNum(id,ItemId))
		
		if(ItemId == Last)
			break
	}
	// the != -1 bit will never happen, it's just to stop the compiler from complaining
	
	/*
	new Success,First = array_first(g_UserItemArray[id],0,Success)
	client_print(id,print_chat,"First: %d,Success: %d",First,Success)
	for(new Num = Start,Count = First;Num < Start + MenuOptions && Count;Count = array_next(g_UserItemArray[id],Count,Success))
	{
		if(!array_isfilled(g_UserItemArray[id],Count))
			break
		
		ItemId = Count
		ItemNum = array_get_int(g_UserItemArray[id],Count)
		
		client_print(id,print_chat,"Loop - ItemId: %d, ItemNum: %d",ItemId,ItemNum)
			
		UTIL_DPRP_ValidItemId(ItemId) ? UTIL_DPRP_GetItemName(ItemId,ItemName,32) : copy(ItemName,32,"BAD ITEMID: Contact admin")
			
		Pos += format(Menu[Pos],Len - Pos,"%d. %s x %d^n",++Num,ItemName,ItemNum)
	}*/
	Pos += format(Menu[Pos],Len - Pos,"^n8. Last Page^n9. Next Page^n^n0. Exit")
	
	show_menu(id,Keys,Menu,-1,g_ItemsMenu)
	
	return PLUGIN_HANDLED
}	

public ItemsHandle(id,Key)
	switch(Key)
	{
		case 7 :
		{
			if(g_MenuPage[id])
				g_MenuPage[id]--
			
			ShowItems(id)
		}
		case 8 :
		{
			new ItemsNum
			USER_ITEM_SCAN
				if(array_isfilled(g_UserItemArray[id],Next) && array_get_int(g_UserItemArray[id],Next))
					ItemsNum++
			
			if((g_MenuPage[id] + 1) * 7 < ItemsNum)
				g_MenuPage[id]++
			
			ShowItems(id)
		}
		case 9 :
			g_MenuPage[id] = 0
		default :
		{
			new Item = g_MenuPage[id] * 7 + Key,Success
			
			/*USER_ITEM_SCAN
				if(ItemNum++ >= Item)
				{
					ItemNum = Next
					break
				}*/
			
			new ItemId = array_get_nth(g_UserItemArray[id],Item + 1,_,Success)			
			g_CurItem[id] = ItemId
			
			if(UTIL_DPRP_ValidItemId(ItemId))
			{
				format(g_Query,511,"DeepPurpleRP Item Options^n^n1. Use^n2. Give^n3. Examine^n4. Show^n5. Drop^n^n0. Exit")
				show_menu(id,g_Keys,g_Query,-1,g_ItemsOptions)
			}
			else
				client_print(id,print_chat,"[DPRP] This item is invalid. Please contact the administrator.")
				
			return
		}
	}

public ItemsOptions(id,Key)
	switch(Key)
	{
		case 0 :
		{
			if(g_ItemUse[id])
			{
				client_print(id,print_chat,"[DPRP] You are already using another item.")
				return
			}
			
			ItemUse(id,g_CurItem[id],1)
		}
		
		case 1 :
		{
			format(g_Query,511,"DeepPurpleRP Give Items^n^n1. Give 1^n2. Give 5^n3. Give 20^n4. Give 50^n5. Give 100^n6. Give All^n^n0. Exit")
			show_menu(id,g_Keys,g_Query,-1,g_ItemsGive)
		}
		
		case 2 :
		{
			new ItemId = g_CurItem[id]
			if(!UTIL_DPRP_ValidItemId(ItemId))
			{
				client_print(id,print_chat,"[DPRP] This item is invalid. Please contact an administrator.")
				return
			}
				
			array_get_string(array_get_int(g_ItemsArray,ItemId),4,g_Query,63)
			
			client_print(id,print_chat,"[DPRP] %s",g_Query)
		}
		
		case 3 :
		{
			new Index,Body
			get_user_aiming(id,Index,Body,100)
			
			if(!Index || !is_user_alive(Index))
				return
	
			new Names[2][33],ItemId = g_CurItem[id],ItemName[33]//_DPRP_GetItemIdCell(0,g_UserItemIds[id][g_CurItem[id]])
			get_user_name(id,Names[0],32)
			get_user_name(Index,Names[1],32)
			
			UTIL_DPRP_GetItemName(ItemId,ItemName,32)
			
			client_print(id,print_chat,"[DPRP] You show %s your %s.",Names[1],ItemName)
			client_print(Index,print_chat,"[DPRP] %s shows you his %s.",Names[0],ItemName)
		}
		
		case 4 :
		{
			format(g_Query,511,"DeepPurpleRP Drop Items^n^n1. Drop 1^n2. Drop 5^n3. Drop 20^n4. Drop 50^n5. Drop 100^n6. Drop All^n^n0. Exit")
			show_menu(id,g_Keys,g_Query,-1,g_ItemsDrop)
		}
	}

public ItemsGive(id,Key)
{
	new Index,Body,Num
	get_user_aiming(id,Index,Body,200)
	
	if(!Index || !is_user_alive(Index))
	{
		client_print(id,print_chat,"[DPRP] You are not looking at a user.")
		return
	}
	
	new ItemId = g_CurItem[id]
	
	switch(Key)
	{
		case 0 :
			Num = 1
		case 1 :
			Num = 5
		case 2 :
			Num = 20
		case 3 :
			Num = 50
		case 4 :
			Num = 100
		case 5 :
			Num = array_get_int(g_UserItemArray[id],g_CurItem[id])
	}
	
	if(ItemId < Num)
	{
		client_print(id,print_chat,"[DPRP] You do not have enough of this item.")		
		return
	}
			
	if(!UTIL_DPRP_SetUserItemNum(Index,ItemId,UTIL_DPRP_GetUserItemNum(Index,ItemId) + Num))
	{
		client_print(id,print_chat,"[DPRP] Sorry, that user cannot accept items right now.")
		return
	}
		
	UTIL_DPRP_SetUserItemNum(id,ItemId,UTIL_DPRP_GetUserItemNum(id,ItemId) - Num)
			
	new Names[2][33],ItemName[33]//= _DPRP_GetItemIdCell(0,g_UserItemIds[id][g_CurItem[id]])
	get_user_name(id,Names[0],32)
	get_user_name(Index,Names[1],32)
	
	UTIL_DPRP_GetItemName(ItemId,ItemName,32)
	
	client_print(id,print_chat,"[DPRP] You have given %s %d %s%s.",Names[1],Num,ItemName,Num == 1 ? "" : "s")
	client_print(Index,print_chat,"[DPRP] %s has given you %d %s%s.",Names[0],Num,ItemName,Num == 1 ? "" : "s")
}	

public ItemsDrop(id,Key)
{
	new Num,ItemNum = array_get_int(g_UserItemArray[id],g_CurItem[id]),ItemId = g_CurItem[id]
	
	switch(Key)
	{
		case 0 :
			Num = 1
		case 1 :
			Num = 5
		case 2 :
			Num = 20
		case 3 :
			Num = 50
		case 4 :
			Num = 100
		case 5 :
			Num = ItemNum
	}
	
	if(ItemNum < Num)
	{
		client_print(id,print_chat,"[DPRP] You do not have enough of this item.")		
		return
	}
			
	UTIL_DPRP_SetUserItemNum(id,ItemId,UTIL_DPRP_GetUserItemNum(id,ItemId) - Num)
	
	new Ent = create_entity("info_target"),Float:Origin[3]
	if(!Ent)
		return
	
	entity_get_vector(id,EV_VEC_origin,Origin)
	entity_set_string(Ent,EV_SZ_classname,g_ItemClassname)
	entity_set_model(Ent,g_ItemModel)
	entity_set_origin(Ent,Origin)
	entity_set_int(Ent,EV_INT_iuser1,ItemId)
	entity_set_int(Ent,EV_INT_iuser2,Num)
	entity_set_size(Ent,Float:{-2.5,-2.5,-2.5},Float:{2.5,2.5,2.5})

	entity_set_origin(id,Float:{0.0,0.0,0.0})
	drop_to_floor(Ent)
	entity_set_origin(id,Origin)
}
	
public client_PreThink(id)
{
	new Index,Body,EntList[1]
	get_user_aiming(id,Index,Body,100)
	
	static Classname[33]
	
	if(entity_get_int(id,EV_INT_button) & IN_USE && !(entity_get_int(id,EV_INT_oldbuttons) & IN_USE))
	{
		if(Index && is_valid_ent(Index))
		{
			entity_get_string(Index,EV_SZ_classname,Classname,32)
			if(equali(Classname,"func_door") || equali(Classname,"func_door_rotating"))
			{
				// is really targetname now, but we should reuse variables
				entity_get_string(Index,EV_SZ_targetname,Classname,32)
				new Property = UTIL_DPRP_GetProperty(Classname,Index)
				if(Property == -1)
					return
				
				new Array = array_get_int(g_PropertyArray,Property)
				
				static Authid[36],EntAuthid[36]
				get_user_authid(id,Authid,35)
				array_get_string(Array,3,EntAuthid,35)
				
				if(!array_get_int(Array,5) || array_get_int(Array,8) & (1<<id) || equali(Authid,EntAuthid))
				{
					client_print(id,print_chat,"[DPRP] You used the door.")
					force_use(id,Index)
					fake_touch(Index,id)
				}
				else
					client_print(id,print_chat,"[DPRP] This door is locked.")
				
				return
			}
		}
		
		if(find_sphere_class(id,g_ItemClassname,50.0,EntList,1))
		{
			new Ent = EntList[0]
			
			new ItemId = entity_get_int(Ent,EV_INT_iuser1),Quantity = entity_get_int(Ent,EV_INT_iuser2),ItemName[33]//,Cell = _DPRP_GetItemIdCell(0,ItemId)
	
			UTIL_DPRP_SetUserItemNum(id,ItemId,UTIL_DPRP_GetUserItemNum(id,ItemId) + Quantity)
			UTIL_DPRP_GetItemName(ItemId,ItemName,32)
	
			client_print(id,print_chat,"[DPRP] You have picked up %d %s%s.",Quantity,ItemName,Quantity == 1 ? "" : "s")
			
			remove_entity(Ent)
			
			return
		}
		
		if(Index && is_valid_ent(Index))
		{
			entity_get_string(Index,EV_SZ_classname,Classname,32)
			if(equal(Classname,g_NpcClassname))
			{
				new Plugin = entity_get_int(Index,EV_INT_iuser3)
				new Handler[32]
				entity_get_string(Index,EV_SZ_noise,Handler,31)
				
				NpcUse(Handler,Plugin,id,Index)
			}	
		}
		
		find_sphere_class(id,g_NpcZoneClassname,100.0,EntList,1)
		if(EntList[0])
		{
			Index = EntList[0]
			
			new Plugin = entity_get_int(Index,EV_INT_iuser3)
			new Handler[32]
			entity_get_string(Index,EV_SZ_noise,Handler,31)
				
			NpcUse(Handler,Plugin,id,Index)
		}
	}	
	
	static Name[33],Message[128]
	
	find_sphere_class(id,g_NpcZoneClassname,100.0,EntList,1)
	if(EntList[0])
	{
		entity_get_string(EntList[0],EV_SZ_noise1,Name,32)
		
		format(Message,127,"%s^nPress use (default e) to use",Name)
		
		UTIL_DPRP_ClientPrint(id,"%s",Message)
	}
	
	if(!Index)
		return
	
	entity_get_string(Index,EV_SZ_classname,Classname,32)
	
	if(equal(Classname,g_NpcClassname))
	{
		entity_get_string(Index,EV_SZ_noise1,Name,32)
		
		format(Message,127,"%s^nPress use (default e) to use",Name)
		
		UTIL_DPRP_ClientPrint(id,"%s",Message)
	}
	else if(equali(Classname,"func_door") || equali(Classname,"func_door_rotating"))
	{
		static Targetname[33],CurTargetname[33]
		entity_get_string(Index,EV_SZ_targetname,CurTargetname,32)
		
		for(new Count;Count < g_DoorNum;Count++)
		{			
			array_get_string(array_get_int(g_DoorArray,Count),0,Targetname,32)
			if((Targetname[0] && equali(Targetname,CurTargetname)) || (array_isfilled(array_get_int(g_DoorArray,Count),1) && Index == array_get_int(array_get_int(g_DoorArray,Count),1)))
			{
				static Ownername[33],Purchase[64]
				
				new Property = UTIL_DPRP_GetProperty(Targetname,Index)
				if(Property == -1)
					return
				
				new Array = array_get_int(g_PropertyArray,Property)
				array_get_string(Array,1,Name,32)
				array_get_string(Array,2,Ownername,32)
				new Price = array_get_int(Array,4)
				
				format(Message,127,"^nOwner: %s",Ownername)
				format(Purchase,63,"^nPrice: $%d. Say /buy to purchase.",Price)
				
				UTIL_DPRP_ClientPrint(id,"%s%s%s^nStatus: %s",Name[0] ? Name : "",Ownername[0] ? Message : "", Price ? Purchase : "",array_get_int(Array,5) ? "Locked" : "Unlocked")
			}
		}
	}
	else if(equali(Classname,"player"))
	{
		static JobName[33],Name[33]
		get_user_name(Index,Name,32)
		array_get_string(array_get_int(g_JobsArray,g_JobId[Index]),1,JobName,32)
		
		UTIL_DPRP_ClientPrint(id,"Name: %s^nJob: %s",Name,JobName)
	}			
}

NpcUse(Handler[],Plugin,id,Index)
{
	new Forward = CreateOneForward(Plugin,Handler,FP_CELL,FP_CELL),Return
	// duplicate code, but whatever
	if(Forward < 0)
	{
		format(g_Query,511,"Function does not exist: %s",Handler)
		return UTIL_DPRP_ThrowError(0,0,g_Query,Plugin)
	}
	
	if(!ExecuteForward(Forward,Return,id,Index))
	{
		format(g_Query,511,"Function does not exist: %s",Handler)
		return UTIL_DPRP_ThrowError(0,0,g_Query,Plugin)
	}
	
	DestroyForward(Forward)
	
	return SUCCEEDED
}

public ForwardTouch(Ptr,Ptd)
{
	if(!pev_valid(Ptr) || !pev_valid(Ptd))
		return FMRES_IGNORED
	
	static Classname[33],Ent
	pev(Ptr,pev_classname,Classname,32)
	
	if(containi(Classname,"door") != -1)
		Ent = Ptr
	else
	{
		pev(Ptd,pev_classname,Classname,32)
		if(containi(Classname,"door") != -1)
			Ent = Ptd
	}
	
	if(Ent && pev(Ent,pev_iuser2))
		return FMRES_SUPERCEDE
	
	return FMRES_IGNORED
}

public plugin_natives()
{
	register_library("dprp")
	
	register_native("DPRP_Version","_DPRP_Version")
	
	register_native("DPRP_SqlHandle","_DPRP_SqlHandle")
	
	register_native("DPRP_GetConfigsdir","_DPRP_GetConfigsdir")
	
	register_native("DPRP_GetNpcClassname","_DPRP_GetNpcClassname")
	register_native("DPRP_RegisterNpc","_DPRP_RegisterNpc")
	register_native("DPRP_IsNpc","_DPRP_IsNpc")
	
	register_native("DPRP_GetUserWallet","_DPRP_GetUserWallet")
	register_native("DPRP_SetUserWallet","_DPRP_SetUserWallet")
	register_native("DPRP_GetUserBank","_DPRP_GetUserBank")
	register_native("DPRP_SetUserBank","_DPRP_SetUserBank")
	register_native("DPRP_GetUserHunger","_DPRP_GetUserHunger")
	register_native("DPRP_SetUserHunger","_DPRP_SetUserHunger")
	register_native("DPRP_GetUserAccess","_DPRP_GetUserAccess")
	register_native("DPRP_SetUserAccess","_DPRP_SetUserAccess")
	
	register_native("DPRP_GetJobsNum","_DPRP_GetJobsNum")
	register_native("DPRP_GetJobName","_DPRP_GetJobName")
	register_native("DPRP_GetJobSalary","_DPRP_GetJobSalary")
	register_native("DPRP_GetJobAccess","_DPRP_GetJobAccess")
	register_native("DPRP_GetUserJobId","_DPRP_GetUserJobId")
	register_native("DPRP_SetUserJobId","_DPRP_SetUserJobId")
	register_native("DPRP_SetUserJobRight","_DPRP_SetUserJobRight")
	register_native("DPRP_GetUserJobRight","_DPRP_GetUserJobRight")
	register_native("DPRP_ValidJobId","_DPRP_ValidJobId")
	register_native("DPRP_FindJobId","_DPRP_FindJobId")
	register_native("DPRP_AddJob","_DPRP_AddJob")
	
	register_native("DPRP_RegisterItem","_DPRP_RegisterItem")
	register_native("DPRP_ValidItemId","_DPRP_ValidItemId")
	register_native("DPRP_FindItemId","_DPRP_FindItemId")
	register_native("DPRP_GetItemName","_DPRP_GetItemName")
	//register_native("DPRP_GetUserItemId","_DPRP_GetUserItemId")
	register_native("DPRP_GetUserItemNum","_DPRP_GetUserItemNum")
	register_native("DPRP_GetUserItems","_DPRP_GetUserItems")
	register_native("DPRP_SetUserItemNum","_DPRP_SetUserItemNum")
	register_native("DPRP_ForceUseItem","_DPRP_ForceUseItem")
	register_native("DPRP_ItemSet","_DPRP_ItemSet")
	register_native("DPRP_ItemDone","_DPRP_ItemDone")
	
	register_native("DPRP_AddCommand","_DPRP_AddCommand")
	
	register_native("DPRP_AddHudItem","_DPRP_AddHudItem")
	
	register_native("DPRP_ValidProperty","_DPRP_ValidProperty")
	register_native("DPRP_ValidPropertyName","_DPRP_ValidPropertyName")
	register_native("DPRP_ValidDoor","_DPRP_ValidDoor")
	register_native("DPRP_ValidDoorName","_DPRP_ValidDoorName")
	register_native("DPRP_AddProperty","_DPRP_AddProperty")
	register_native("DPRP_AddDoor","_DPRP_AddDoor")
	register_native("DPRP_PropertyNum","_DPRP_PropertyNum")
	register_native("DPRP_DoorNum","_DPRP_DoorNum")
	register_native("DPRP_PropertyMatch","_DPRP_PropertyMatch")
	register_native("DPRP_PropertyGetExternalName","_DPRP_PropertyGetExternalName")
	register_native("DPRP_PropertySetExternalName","_DPRP_PropertySetExternalName")
	register_native("DPRP_PropertyGetOwnerName","_DPRP_PropertyGetOwnerName")
	register_native("DPRP_PropertySetOwnerName","_DPRP_PropertySetOwnerName")
	register_native("DPRP_PropertyGetOwnerAuth","_DPRP_PropertyGetOwnerAuth")
	register_native("DPRP_PropertySetOwnerAuth","_DPRP_PropertySetOwnerAuth")
	register_native("DPRP_PropertyGetPrice","_DPRP_PropertyGetPrice")
	register_native("DPRP_PropertySetPrice","_DPRP_PropertySetPrice")
	register_native("DPRP_PropertyGetLocked","_DPRP_PropertyGetLocked")
	register_native("DPRP_PropertySetLocked","_DPRP_PropertySetLocked")
	register_native("DPRP_PropertyGetAccess","_DPRP_PropertyGetAccess")
	register_native("DPRP_PropertySetAccess","_DPRP_PropertySetAccess")
	register_native("DPRP_PropertyGetProfit","_DPRP_PropertyGetProfit")
	register_native("DPRP_PropertySetProfit","_DPRP_PropertySetProfit")
	register_native("DPRP_PropertyAddAccess","_DPRP_PropertyAddAccess")
	register_native("DPRP_PropertyRemoveAccess","_DPRP_PropertyRemoveAccess")
	
	register_native("DPRP_GetRob","_DPRP_GetRob")
	register_native("DPRP_EndRob","_DPRP_EndRob")
	register_native("DPRP_Rob","_DPRP_Rob")
	
	register_native("DPRP_ThrowError","_DPRP_ThrowError")
	register_native("DPRP_ClientPrint","_DPRP_ClientPrint")
}

public _DPRP_Version(Plugin,Params)
{
	if(Params == 2)
		set_string(1,g_Version,get_param(2))
	else
	{
		format(g_Query,511,"Parameters do not match. Expected: 2 or more, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return SUCCEEDED
}

public _DPRP_ClientPrint(Plugin,Params)
{
	if(Params < 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2 or more, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1)
	get_string(2,g_Query,511)
	
	if(!is_user_connected(id) && id)
	{
		format(g_Query,511,"User is not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	vformat(g_Query,511,g_Query,3)
	
	UTIL_DPRP_ClientPrint(id,g_Query)
	
	return SUCCEEDED
}

public _DPRP_GetConfigsdir(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	set_string(1,g_ConfigsDir,get_param(2))
	
	return SUCCEEDED
}

public _DPRP_GetUserJobRight(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1)
	if(is_user_connected(id))
		return g_JobRight[id]
	else
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return FAILED
}

public _DPRP_SetUserJobRight(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1),Rights = get_param(2),Set
	for(new Count;Count < JOB_ACCESSES;Count++)
		if(Rights & (1<<Count))
			Set |= (1<<Count)
	
	if(is_user_connected(id))
		return g_JobRight[id] = Set
	else
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
		
	return FAILED
}

public _DPRP_EndRob(Plugin,Params)
{
	if(Params < 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: < 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1),Reason[128]
	get_string(2,Reason,127)
	
	if(!is_user_connected(id))
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	vformat(Reason,127,Reason,2)
	
	return EndRob(id,Reason)
}

public _DPRP_GetRob(Plugin,Params)
{
	if(Params != 5)
	{
		format(g_Query,511,"Parameters do not match. Expected: 5, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
		
	new id = get_param(1)
	
	if(!is_user_connected(id))
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(g_EdekaRobber != id && g_DinerRobber != id && g_BankRobber != id)
	{
		format(g_Query,511,"User %d is not robbing any place.",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	set_param_byref(2,g_RobInfo[id][1])
	set_param_byref(3,g_RobInfo[id][2])
	set_param_byref(4,g_RobInfo[id][3])
	set_param_byref(5,g_RobInfo[id][4])
	
	return SUCCEEDED
}

public _DPRP_ItemSet(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1)
	if(is_user_connected(id))
		return g_ItemUse[id] = Plugin
	else
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return FAILED
}

public _DPRP_ValidItemId(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return UTIL_DPRP_ValidItemId(get_param(1) - 1)
}

public _DPRP_ForceUseItem(Plugin,Params)
{
	if(Params != 3)
	{
		format(g_Query,511,"Parameters do not match. Expected: 3, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1),ItemId = get_param(2),UseUp = get_param(3)
	
	if(!is_user_connected(id))
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(UseUp && !UTIL_DPRP_GetUserItemNum(id,ItemId))
	{
		format(g_Query,511,"User %d has none of item: %d",id,ItemId)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(g_ItemUse[id])
		return FAILED
	
	if(UTIL_DPRP_ValidItemId(ItemId))
		return ItemUse(id,ItemId,UseUp ? 1 : 0)
	
	format(g_Query,511,"Invalid item id: %d",ItemId)
	return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
}

public _DPRP_AddJob(Plugin,Params)
{
	if(Params != 3)
	{
		format(g_Query,511,"Parameters do not match. Expected: 3, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Name[33],Salary,IntAccess
	
	get_string(1,Name,32)
	Salary = get_param(2)
	IntAccess = get_param(3)
	
	new Results[1]
	DPRP_FindJobId(Name,Results,1)
	
	if(Results[0])
	{
		Results[0] -= 1
		
		new TempName[33]
		array_get_string(array_get_int(g_JobsArray,Results[0]),1,TempName,32)
		
		format(g_Query,511,"A job with a similar name already exists. User input: %s - Existing job: %s",Name,TempName)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Access[JOB_ACCESSES + 1]
	DPRP_IntToAccess(IntAccess,Access,JOB_ACCESSES)
	
	format(g_Query,511,"INSERT INTO %s VALUES ('%s','%d','%s')",g_JobsTable,Name,Salary,Access)
	SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
	
	new Array = array_create()
	array_set_int(g_JobsArray,g_JobsNum++,Array)
	
	array_set_string(Array,1,Name)
	array_set_int(Array,2,Salary)
	array_set_int(Array,3,IntAccess)
	
	return g_JobsNum
}
	
public _DPRP_Rob(Plugin,Params)
{	
	if(Params != 5)
	{
		format(g_Query,511,"Parameters do not match. Expected: 5, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
		
	new id = get_param(1),CashSecond = get_param(2),CashMax = get_param(3),Targetname[33],Type = get_param(5)
	get_string(4,Targetname,32)
	
	if(!is_user_connected(id))
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(CashSecond < 1)
	{
		format(g_Query,511,"CashSecond must be greater than 0, value: %d",CashSecond)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(CashMax < 1)
	{
		format(g_Query,511,"CashMax must be greater than 0, value: %d",CashMax)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Ent = find_ent_by_tname(-1,Targetname)
	if(!Ent)
	{
		format(g_Query,511,"Invalid targetname: %s",Targetname)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Time = floatround(get_gametime()),Name[33]
	get_user_name(id,Name,32)
	
	set_hudmessage(255,255,0,-1.0,0.35,0,0.0,8.0,0.0,0.0,-1)
	switch(Type)
	{
		case EDEKA711 :
		{
			if(DPRP_IsCop(id))
			{
				client_print(id,print_chat,"[DPRP] Police, SWAT and Army men cannot rob.")
				return FAILED
			}
			if(Time - g_LastEdekaRob < get_pcvar_num(p_EdekaRobWait) && g_LastEdekaRob)
			{
				client_print(id,print_chat,"[DPRP] This place has already been robbed recently.")
				return FAILED
			}
			if(get_pcvar_num(p_EdekaMinPlayers) > get_playersnum())
			{
				client_print(id,print_chat,"[DPRP] There are not enough players to rob this place.")
				return FAILED
			}
			
			new Cops
			for(new Count = 1;Count <= 32;Count++)
				if(is_user_connected(Count) && DPRP_IsCop(Count))
					Cops++
			
			if(Cops < get_pcvar_num(p_EdekaMinCops))
			{
				client_print(id,print_chat,"[DPRP] There are not enough police/SWAT/army players to rob this place.")
				return FAILED
			}
			
			if(!RobForward(id,CashSecond,CashMax,Targetname,Type))
				return FAILED
			
			g_LastEdekaRob = Time
			
			g_EdekaRobber = id
			
			switch(get_pcvar_num(p_RobHud))
			{
				case 0 : 
				{
				}
				case 1 :
				{
					copy(Name,32,"Someone")
					show_hudmessage(0,"%s is robbing the 7/11!",Name)
				}
				case 2 :
					show_hudmessage(0,"%s is robbing the 7/11!",Name)
			}		
		}
		case DINER :
		{
			if(DPRP_IsCop(id))
			{
				client_print(id,print_chat,"[DPRP] Police, SWAT and Army men cannot rob.")
				return FAILED
			}
			if(Time - g_LastDinerRob < get_pcvar_num(p_DinerRobWait) && g_LastDinerRob)
			{
				client_print(id,print_chat,"[DPRP] This place has already been robbed recently.")
				return FAILED
			}
			if(get_pcvar_num(p_DinerMinPlayers) > get_playersnum())
			{
				client_print(id,print_chat,"[DPRP] There are not enough players to rob this place.")
				return FAILED
			}
			
			new Cops
			for(new Count = 1;Count <= 32;Count++)
				if(is_user_connected(Count) && DPRP_IsCop(Count))
					Cops++
			
			if(Cops < get_pcvar_num(p_DinerMinCops))
			{
				client_print(id,print_chat,"[DPRP] There are not enough police/SWAT/army players to rob this place.")
				return FAILED
			}
			
			if(!RobForward(id,CashSecond,CashMax,Targetname,Type))
				return FAILED
			
			g_LastDinerRob = Time
			
			g_DinerRobber = id
			
			switch(get_pcvar_num(p_RobHud))
			{
				case 0 : 
				{
				}
				case 1 :
				{
					copy(Name,32,"Someone")
					show_hudmessage(0,"%s is emptying the diner!",Name)
				}
				case 2 :
					show_hudmessage(0,"%s is emptying the diner!",Name)
			}
		}
		case BANK :
		{		
			if(DPRP_IsCop(id))
			{
				client_print(id,print_chat,"[DPRP] Police, SWAT and Army men cannot rob.")
				return FAILED
			}
			if(Time - g_LastBankRob < get_pcvar_num(p_BankRobWait) && g_LastBankRob)
			{
				client_print(id,print_chat,"[DPRP] This place has already been robbed recently.")
				return FAILED
			}
			if(get_pcvar_num(p_BankMinPlayers) > get_playersnum())
			{
				client_print(id,print_chat,"[DPRP] There are not enough players to rob this place.")
				return FAILED
			}
			
			new Cops
			for(new Count = 1;Count <= 32;Count++)
				if(is_user_connected(Count) && DPRP_IsCop(Count))
					Cops++
			
			if(Cops < get_pcvar_num(p_BankMinCops))
			{
				client_print(id,print_chat,"[DPRP] There are not enough police/SWAT/army players to rob this place.")
				return FAILED
			}
			
			if(!RobForward(id,CashSecond,CashMax,Targetname,Type))
				return FAILED
				
			new Targetname[33]
			get_pcvar_string(p_BankTargetname,Targetname,32)
			
			new Bank
			while((Bank = find_ent_by_tname(Bank,Targetname)) != 0)
			{
				force_use(id,Bank)
				fake_touch(Bank,id)
			}
			
			g_LastBankRob = Time
			
			new Array[2]
			Array[0] = id
			Array[1] = 0
			
			g_BankRobber = id
			
			g_BankMoneyTaken = 0
			
			set_task(1.0,"BankRob",_,Array,2)
			
			switch(get_pcvar_num(p_RobHud))
			{
				case 0 : 
				{
				}
				case 1 :
				{
					copy(Name,32,"Someone")
					show_hudmessage(0,"Attention all police, army and SWAT units^n%s is robbing the bank!",Name)
				}
				default : 
					show_hudmessage(0,"Attention all police, army and SWAT units^n%s is robbing the bank!",Name)
			}
		}
	}
		
	force_use(id,Ent)
	fake_touch(Ent,id)
	
	entity_get_vector(id,EV_VEC_origin,g_RobOrigin[id])
	
	set_rendering(id,kRenderFxGlowShell,0,255,255,kRenderNormal,16)
	
	if(Type == BANK)
		return SUCCEEDED
	
	new Array[5]
	Array[0] = id
	Array[1] = CashSecond
	Array[2] = CashMax
	Array[3] = 0
	Array[4] = Type
	
	g_RobInfo[id] = Array
	
	set_task(1.0,"AddCash",_,Array,5)
	
	return SUCCEEDED
}

RobForward(id,CashSecond,CashMax,Targetname[],Type)
{
	new Forward = CreateMultiForward("DPRP_UserRob",ET_STOP2,FP_CELL,FP_CELL,FP_CELL,FP_STRING,FP_CELL),Return
	if(Forward < 0)
	{
		format(g_Query,511,"Could not call DPRP_UserRob forward.")
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,0)
	}
	
	if(!ExecuteForward(Forward,Return,id,CashSecond,CashMax,Targetname,Type))
	{
		format(g_Query,511,"Could not call DPRP_UserRob forward.")
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,0)
	}
	
	DestroyForward(Forward)
	
	return SUCCEEDED
}

public BankRob(Array[2])
{
	if(g_BankRobber != Array[0])
		return
	
	new Float:Origin[3],StrTemp[24],TempOrigins[3][6],Ents[1]
	get_pcvar_string(p_MoneyOrigin,StrTemp,23)
	
	parse(StrTemp,TempOrigins[0],5,TempOrigins[1],5,TempOrigins[2],5)
	
	for(new Count;Count < 3;Count++)
		Origin[Count] = str_to_float(TempOrigins[Count])
	
	find_sphere_class(0,"func_pushable",250.0,Ents,1,Origin)
	
	if(Ents[0] == g_BagEnts[0] || Ents[0] == g_BagEnts[1])		
	{
		entity_set_origin(Ents[0],Float:{4096.0,4096.0,4096.0})
		set_task(get_pcvar_float(p_BankRobWait),"RestoreOrigin",Ents[0])
		
		client_print(Array[0],print_chat,"[DPRP] You have brought one money bag to the safe place.")
		
		g_Money[Array[0]] += get_pcvar_num(p_BankRobMoney) //DPRP_SetUserWallet(Array[0],DPRP_GetUserWallet(Array[0]) + get_pcvar_num(p_BankRobMoney))
		
		if(++g_BankMoneyTaken >= 2)
		{
			client_print(Array[0],print_chat,"[DPRP] You have brought all the money bags to the safe place! Run!")
			
			EndRob(Array[0],"#name# has retrieved all the money bags from the bank")
			
			new Targetname[33]
			get_pcvar_string(p_BankTargetname,Targetname,32)
			
			new Bank
			while((Bank = find_ent_by_tname(Bank,Targetname)) != 0)
			{
				force_use(Array[0],Bank)
				fake_touch(Bank,Array[0])
			}
			
			return
		}
	}
	
	new RobTime = get_pcvar_num(p_BankRobTime)
		
	if(Array[1] >= RobTime)
	{
		client_print(Array[0],print_chat,"[DPRP] You have ran out of time to rob the bank.")
		
		EndRob(Array[0],"#name# ran out of time to rob the bank")
		
		return
	}
	
	Array[1] += 1
	
	set_hudmessage(255,0,0,-0.85,-0.85,0,0.0,8.0,0.0,0.0,3)
	show_hudmessage(Array[0],"Time Left: %ds",RobTime - Array[1])
	
	set_task(1.0,"BankRob",_,Array,2)
}

public RestoreOrigin(Ent)
	if(Ent == g_BagEnts[0])
		entity_set_origin(Ent,g_BagOrigin[0])
	else if(Ent == g_BagEnts[1])
		entity_set_origin(Ent,g_BagOrigin[1])

public AddCash(Array[5])
{
	g_RobInfo[Array[0]] = Array
	
	new Float:Origin[3]
	entity_get_vector(Array[0],EV_VEC_origin,Origin)
	
	if(get_distance_f(g_RobOrigin[Array[0]],Origin) > 250.0)
	{
		client_print(Array[0],print_chat,"[DPRP] You have strayed too far from the register, run!")
		
		EndRob(Array[0],"#name# is running away, catch him!")
		
		return
	}
	
	Array[3] += Array[1]
	g_Money[Array[0]] += Array[1]
	
	if(Array[3] >= Array[2])
	{
		client_print(Array[0],print_chat,"[DPRP] You have finished robbing, run!")
		
		EndRob(Array[0],"#name# is running away, catch him!")
		
		return
	}
	
	set_task(1.0,"AddCash",_,Array,5)
}

public _DPRP_AddProperty(Plugin,Params)
{
	if(Params != 8)
	{
		format(g_Query,511,"Parameters do not match. Expected: 5, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new InternalName[64],ExternalName[64],OwnerName[33],OwnerAuth[36],Price,Locked,Access,Profit
	get_string(1,InternalName,63)
	get_string(2,ExternalName,63)
	get_string(3,OwnerName,32)
	get_string(4,OwnerAuth,35)
	Price = get_param(5)
	Locked = get_param(6)
	Access = get_param(7)
	Profit = get_param(8)
	
	if(UTIL_DPRP_MatchProperty(InternalName) != -1)
	{
		format(g_Query,511,"Property already exists: %s",InternalName)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Array = array_create()
	array_set_int(g_PropertyArray,g_PropertyNum++,Array)
	
	array_set_string(Array,0,InternalName)
	array_set_string(Array,1,ExternalName)
	array_set_string(Array,2,OwnerName)
	array_set_string(Array,3,OwnerAuth)
	array_set_int(Array,4,Price)
	array_set_int(Array,5,Locked)
	array_set_int(Array,6,Access)
	array_set_int(Array,7,Profit)
	array_set_int(Array,8,0)
	
	//format(g_Query,511,"INSERT INTO %s VALUES ('%s','%s','','','%d','0','','0','','%s')",g_PropertyTable,Targetname,Name,Price,FakeMsg)
	//SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
	
	return g_PropertyNum
}

public _DPRP_AddDoor(Plugin,Params)
{
	if(Params != 3)
	{
		format(g_Query,511,"Parameters do not match. Expected: 5, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Targetname[33],EntID,InternalName[64]
	get_string(1,Targetname,32)
	EntID = get_param(2)
	get_string(3,InternalName,63)
	
	if(UTIL_DPRP_GetProperty(Targetname,EntID) != -1)
	{
		format(g_Query,511,"Door already exists: %s/%d",Targetname,EntID)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(UTIL_DPRP_MatchProperty(InternalName) == -1)
	{
		format(g_Query,511,"Property does not exist: %s",InternalName)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Array = array_create()
	array_set_int(g_DoorArray,g_DoorNum++,Array)
	
	array_set_string(Array,0,Targetname)
	array_set_int(Array,1,EntID)
	array_set_string(Array,2,InternalName)
	
	return g_DoorNum
}

/*public _DPRP_RemoveProperty(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
}*/

public _DPRP_ValidProperty(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return UTIL_DPRP_ValidProperty(get_param(1) - 1)
}

public _DPRP_ValidDoor(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return UTIL_DPRP_ValidDoor(get_param(1) - 1)
}

public _DPRP_ValidPropertyName(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new InternalName[64]
	get_string(1,InternalName,63)
	
	if(UTIL_DPRP_MatchProperty(InternalName) != -1)
		return SUCCEEDED
	
	return FAILED
}
	
public _DPRP_ValidDoorName(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
		
	new Ent = get_param(1),Targetname[33]
	get_string(2,Targetname,32)
	
	if(UTIL_DPRP_GetProperty(Targetname,Ent) != -1)
		return SUCCEEDED
	
	return FAILED
}

public _DPRP_PropertyNum()
	return g_PropertyNum

public _DPRP_DoorNum()
	return g_DoorNum

public _DPRP_PropertyMatch(Plugin,Params)
{
	if(Params != 3)
	{
		format(g_Query,511,"Parameters do not match. Expected: 3, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Targetname[33],EntID = get_param(2),InternalName[64]
	get_string(1,Targetname,32)
	get_string(3,InternalName,63)
	
	if(Targetname[0] || EntID)
		return UTIL_DPRP_GetProperty(Targetname,EntID) + 1
		
	return UTIL_DPRP_MatchProperty(InternalName) + 1
}

public _DPRP_PropertySetExternalName(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1,ExternalName[64]
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	get_string(2,ExternalName,63)
	array_set_string(array_get_int(g_PropertyArray,Property),1,ExternalName)
	
	return SUCCEEDED
}

public _DPRP_PropertyGetExternalName(Plugin,Params)
{
	if(Params != 3)
	{
		format(g_Query,511,"Parameters do not match. Expected: 3, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1,ExternalName[64]
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	array_get_string(array_get_int(g_PropertyArray,Property),1,ExternalName,63)
	set_string(2,ExternalName,get_param(3))
	
	return SUCCEEDED
}

public _DPRP_PropertySetOwnerName(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1,OwnerName[33]
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	get_string(2,OwnerName,32)
	array_set_string(array_get_int(g_PropertyArray,Property),2,OwnerName)
	
	return SUCCEEDED
}

public _DPRP_PropertyGetOwnerName(Plugin,Params)
{
	if(Params != 3)
	{
		format(g_Query,511,"Parameters do not match. Expected: 3, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1,OwnerName[33]
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	array_get_string(array_get_int(g_PropertyArray,Property),2,OwnerName,33)
	set_string(2,OwnerName,get_param(3))
	
	return SUCCEEDED
}

public _DPRP_PropertySetOwnerAuth(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1,OwnerAuth[33]
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	get_string(2,OwnerAuth,32)
	array_set_string(array_get_int(g_PropertyArray,Property),3,OwnerAuth)
	
	return SUCCEEDED
}

public _DPRP_PropertyGetOwnerAuth(Plugin,Params)
{
	if(Params != 3)
	{
		format(g_Query,511,"Parameters do not match. Expected: 3, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1,OwnerAuth[33]
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	array_get_string(array_get_int(g_PropertyArray,Property),3,OwnerAuth,33)
	set_string(2,OwnerAuth,get_param(3))
	
	return SUCCEEDED
}

public _DPRP_PropertySetPrice(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	array_set_int(array_get_int(g_PropertyArray,Property),4,max(0,get_param(2)))
	
	return SUCCEEDED
}

public _DPRP_PropertyGetPrice(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return array_get_int(array_get_int(g_PropertyArray,Property),4)
}

public _DPRP_PropertySetLocked(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	array_set_int(array_get_int(g_PropertyArray,Property),5,get_param(2) ? 1 : 0)
	
	return SUCCEEDED
}

public _DPRP_PropertyGetLocked(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return array_get_int(array_get_int(g_PropertyArray,Property),5)
}

public _DPRP_PropertySetAccess(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	array_set_int(array_get_int(g_PropertyArray,Property),6,get_param(2))
	
	return SUCCEEDED
}

public _DPRP_PropertyGetAccess(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return array_get_int(array_get_int(g_PropertyArray,Property),6)
}

public _DPRP_PropertySetProfit(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	array_set_int(array_get_int(g_PropertyArray,Property),7,max(0,get_param(2)))
	
	return SUCCEEDED
}

public _DPRP_PropertyGetProfit(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return array_get_int(array_get_int(g_PropertyArray,Property),7)
}

public _DPRP_PropertyAddAccess(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1,Authid[36],MapName[33],InternalName[64]
	get_string(2,Authid,35)
	get_mapname(MapName,32)
	
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Array = array_get_int(g_PropertyArray,Property)
	array_get_string(Array,0,InternalName,63)
	
	format(g_Query,511,"INSERT INTO %s VALUES('%s','%s','%s')",g_KeysTable,Authid,InternalName,MapName)
	SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
	
	new PlayerAuthid[36],Players[32],Playersnum,Player
	get_players(Players,Playersnum)
	
	for(new Count;Count < Playersnum;Count++)
	{
		Player = Players[Count]
		get_user_authid(Player,PlayerAuthid,35)
		
		if(equali(Authid,PlayerAuthid))
		{
			array_set_int(Array,8,array_get_int(Array,8)|(1<<Player))
			break
		}
	}
	
	return SUCCEEDED
}

public _DPRP_PropertyRemoveAccess(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Property = get_param(1) - 1,Authid[36],MapName[33],InternalName[64]
	get_string(2,Authid,35)
	get_mapname(MapName,32)
	
	if(!UTIL_DPRP_ValidProperty(Property))
	{
		format(g_Query,511,"Property does not exist: %d",Property)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Array = array_get_int(g_PropertyArray,Property)
	array_get_string(Array,0,InternalName,63)
	
	format(g_Query,511,"DELETE FROM %s WHERE authid='%s' AND internalname='%s' AND mapname='%s'",g_KeysTable,Authid,InternalName,MapName)
	SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
	
	new PlayerAuthid[36],Players[32],Playersnum,Player
	get_players(Players,Playersnum)
	
	for(new Count;Count < Playersnum;Count++)
	{
		Player = Players[Count]
		get_user_authid(Player,PlayerAuthid,35)
		
		if(equali(Authid,PlayerAuthid) && array_get_int(Array,8) & (1<<Player))
		{
			array_set_int(Array,8,array_get_int(Array,8) - (1<<Player))
			break
		}
	}
	
	return SUCCEEDED
}

public _DPRP_AddHudItem(Plugin,Params)
{
	if(Params != 3)
	{
		format(g_Query,511,"Parameters do not match. Expected: 3, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1),Channel = get_param(2)
	if(!is_user_connected(id))
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(Channel < 0 || Channel > HUD_NUM)
	{
		format(g_Query,511,"Invalid channel: %d",Channel)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(!g_HudPending)
	{
		format(g_Query,511,"This native must be called during the forward ^"DPRP_HudDisplay^".")
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(g_HudNum[id][Channel] >= MAX_HUD_ITEMS)
		return FAILED
	
	get_string(3,g_HudItems[id + 32 *Channel][g_HudNum[id][Channel]],63)
	while(replace(g_HudItems[id + 32 * Channel][g_HudNum[id][Channel]],63,"^n","")) { }
	
	// do NOT ADD THIS TO THE WHILE LOOP, I made a stupid mistake with that before
	g_HudNum[id][Channel]++
	
	return SUCCEEDED
}

public _DPRP_SqlHandle(Plugin,Params)
	return _:g_SqlHandle

public _DPRP_GetNpcClassname(Plugin,Params)
{
	if(Params != 2)	
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	set_string(1,g_NpcClassname,get_param(2))
	
	return SUCCEEDED
}

public _DPRP_GetUserWallet(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1)
	
	if(is_user_connected(id))
		return g_Money[id]
	else
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return FAILED
}

public _DPRP_SetUserWallet(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1)
	
	if(is_user_connected(id))
		return g_Money[id] = get_param(2)
	else
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
		
	return FAILED
}

public _DPRP_GetUserBank(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1)
	
	if(is_user_connected(id))	
		return g_BankMoney[id]
	else
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return FAILED
}

public _DPRP_SetUserBank(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1)
	
	if(is_user_connected(id))
		return g_BankMoney[id] = get_param(2)
	else
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return FAILED
}

public _DPRP_GetUserHunger(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1)

	if(is_user_connected(id))	
		return g_Hunger[id] / 10
	else
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
		
	return FAILED
}

public _DPRP_SetUserHunger(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1)
	
	if(is_user_connected(id))
		return g_Hunger[id] = clamp(get_param(2),0,100) * 10
	else
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return FAILED
}

public _DPRP_GetUserAccess(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1)
	if(is_user_connected(id))
		return g_Access[id]
	else
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return FAILED
}

public _DPRP_SetUserAccess(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1),Access = get_param(2)
	if(is_user_connected(id))
	{
		g_Access[id] = Access
		g_Access[id] |= array_get_int(array_get_int(g_JobsArray,g_JobId[id]),3)
					
		g_AccessCache[id] = Access
	}
	else
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return SUCCEEDED
}

public _DPRP_GetJobsNum(Plugin,Params)
{
	// if it is anything other than 0
	if(Params)
	{
		format(g_Query,511,"Parameters do not match. Expected: 0, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return array_size(g_ItemsArray)
}

public _DPRP_GetJobName(Plugin,Params)
{
	if(Params != 3)
	{
		format(g_Query,511,"Parameters do not match. Expected: 3, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new JobId = get_param(1) - 1,Name[33]
	
	if(!UTIL_DPRP_ValidJobId(JobId))
	{
		format(g_Query,511,"Invalid job id: %d",JobId)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	array_get_string(array_get_int(g_JobsArray,JobId),1,Name,32)
			
	set_string(2,Name,get_param(3))
	
	return SUCCEEDED
}

public _DPRP_GetJobSalary(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new JobId = get_param(1) - 1
	
	if(!UTIL_DPRP_ValidJobId(JobId))
	{
		format(g_Query,511,"Invalid job id: %d",JobId)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return array_get_int(array_get_int(g_JobsArray,JobId),2)
}

public _DPRP_GetJobAccess(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new JobId = get_param(1) - 1
	
	if(!UTIL_DPRP_ValidJobId(JobId))
	{
		format(g_Query,511,"Invalid job id: %d",JobId)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return array_get_int(array_get_int(g_JobsArray,JobId),3)
}
	
public _DPRP_GetUserJobId(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1)
	
	if(is_user_connected(id))
		return g_JobId[id] + 1
	else
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return FAILED
}

public _DPRP_SetUserJobId(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new JobId = get_param(2) - 1,id = get_param(1)
	
	if(!UTIL_DPRP_ValidJobId(JobId))
	{
		format(g_Query,511,"Invalid job id: %d",JobId)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(!is_user_connected(id))
	{
		format(g_Query,511,"User not connected: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}

	g_JobId[id] = JobId
	g_Access[id] = g_AccessCache[id]
	
	g_Salary[id] = array_get_int(array_get_int(g_JobsArray,JobId),2)
	//g_Access[id] |= g_JobAccess[g_JobId[id]]
	g_Access[id] |= array_get_int(array_get_int(g_JobsArray,JobId),3)
	
	return SUCCEEDED
}

public _DPRP_ValidJobId(Plugin,Params)
{
	if(Params != 1 && Plugin)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new JobId = get_param(1) - 1
	
	return UTIL_DPRP_ValidJobId(JobId)
}

public _DPRP_FindJobId(Plugin,Params)
{
	if(Params != 3)
	{
		format(g_Query,511,"Parameters do not match. Expected: 3, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
		
	new SearchString[64],Results[256],MaxResults = get_param(3),Num,Name[33]
	get_string(1,SearchString,63)
	
	for(new Count;Count < g_JobsNum;Count++)
	{		
		if(Num >= MaxResults)
			break
		
		array_get_string(array_get_int(g_JobsArray,Count),1,Name,32)
		if(containi(Name,SearchString) != -1)
			Results[Num++] = Count + 1
	}
	
	set_array(2,Results,MaxResults)
	
	return Num
}	

public _DPRP_RegisterItem(Plugin,Params)
{
	if(Params != 4)
	{
		format(g_Query,511,"Parameters do not match. Expected: 4, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(!g_RegisterItem)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,"DPRP_RegisterItem can only be run in the ^"DPRP_RegisterItems^" forward.",Plugin)
		
	new Name[33],Handler[33],Description[64]//,ItemId = get_param(2)
	get_string(1,Name,32)
	get_string(2,Handler,32)
	get_string(3,Description,63)
	
	//for(new Count;Count < MAX_ITEMS;Count++)
	//	if(equali(Name,g_ItemsNames[Count]) || ItemId == g_ItemsIds[Count])
	//		return FAILED
	
	new Len = strlen(Name)
	if(!Len)
	{
		format(g_Query,511,"Name must have a length.",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new CheckName[33]
	for(new Count;Count < g_ItemsNum;Count++)
	{
		array_get_string(array_get_int(g_ItemsArray,Count),1,CheckName,32)
		if(equali(Name,CheckName))
		{
			format(g_Query,511,"Item collision detected, name: %s",Name)
			return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
		}
	}
			
	new Array = array_create()
	
	array_set_int(g_ItemsArray,g_ItemsNum++,Array)
	array_set_string(Array,1,Name)
	array_set_int(Array,2,Plugin)
	array_set_string(Array,3,Handler)
	array_set_string(Array,4,Description)
	array_set_int(Array,5,get_param(4) ? 1 : 0)
	
	// this will start it at 1 externally, but 0 internally
	return g_ItemsNum
}

public _DPRP_FindItemId(Plugin,Params)
{
	if(Params != 3)
	{
		format(g_Query,511,"Parameters do not match. Expected: 3, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
		
	new Item[33],MaxResults = get_param(3),Num,Name[33],Results[512]
	get_string(1,Item,32)
	
	for(new Count;Count < g_ItemsNum && Num < MaxResults;Count++)
	{
		array_get_string(array_get_int(g_ItemsArray,Count),1,Name,32)
		
		if(containi(Name,Item) != -1)
			Results[Num++] = Count + 1
	}
	
	set_array(2,Results,MaxResults)
	
	return Num
}

public _DPRP_GetItemName(Plugin,Params)
{
	if(Params != 3)
	{
		format(g_Query,511,"Parameters do not match. Expected: 3, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
		
	new ItemId = get_param(1) - 1,Name[33]
	/*for(new Count;Count < g_ItemsNum;Count++)
		if(g_ItemsIds[Count] == ItemId)
			return SUCCEEDED + set_string(2,g_ItemsNames[Count],get_param(3))*/
		
	UTIL_DPRP_GetItemName(ItemId,Name,32)
	
	if(!Name[0])
	{
		format(g_Query,511,"Invalid item id: %d",ItemId + 1)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	set_string(2,Name,get_param(3))
	
	return SUCCEEDED
}

public _DPRP_RegisterNpc(Plugin,Params)
{
	if(Params != 6)
	{
		format(g_Query,511,"Parameters do not match. Expected: 6, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Float:Origin[3],Float:Angles[3],Model[64],Name[33],Handler[32],Zone
	
	get_string(1,Name,32)
	get_array_f(2,Origin,3)
	Angles[1] = get_param_f(3) - 180
	get_string(4,Model,63)
	get_string(5,Handler,31)
	Zone = get_param(6)
	
	if(Zone)
	{
		new Ent = create_entity("info_target")
		if(!Ent)
		{
			format(g_Query,511,"Unable to spawn NPC.",Params)
			return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,0)
		}
		
		entity_set_string(Ent,EV_SZ_classname,g_NpcZoneClassname)
		entity_set_model(Ent,g_FillModel)
		//entity_set_model(Ent,"")
		entity_set_origin(Ent,Origin)
		entity_set_size(Ent,Float:{-16.0,-16.0,-36.0},Float:{16.0,16.0,36.0})
		entity_set_int(Ent,EV_INT_solid,SOLID_TRIGGER)
		entity_set_byte(Ent,EV_BYTE_controller1,125)
		entity_set_byte(Ent,EV_BYTE_controller2,125)
		entity_set_byte(Ent,EV_BYTE_controller3,125)
		entity_set_byte(Ent,EV_BYTE_controller4,125)
		entity_set_int(Ent,EV_INT_sequence,1)
		entity_set_float(Ent,EV_FL_framerate,1.0)
		entity_set_vector(Ent,EV_VEC_angles,Angles)
		entity_set_int(Ent,EV_INT_iuser3,Plugin)
		entity_set_string(Ent,EV_SZ_noise,Handler)
		entity_set_string(Ent,EV_SZ_noise1,Name)
		
		return Ent
	}
	
	/*new Ent = engfunc(EngFunc_CreateNamedEntity,engfunc(EngFunc_AllocString,"info_target"))
	if(!pev_valid(Ent))
		return FAILED
		
	set_pev(Ent,pev_classname,g_NpcClassname)
	set_pev(Ent,pev_model,Model)
	engfunc(EngFunc_SetOrigin,Ent,Origin)
	engfunc(EngFunc_SetSize,Ent,Float:{-16.0,-16.0,-36.0},Float:{16.0,16.0,36.0})
	set_pev(Ent,pev_solid,SOLID_BBOX)
	set_pev(Ent,pev_controller_0,125)
	set_pev(Ent,pev_controller_1,125)
	set_pev(Ent,pev_controller_2,125)
	set_pev(Ent,pev_controller_3,125)
	set_pev(Ent,pev_angles,Angles)*/
	
	Origin[2] += 36.1
	
	if(PointContents(Origin) != CONTENTS_EMPTY)
		Origin[2] -= 36.1
	
	new Ent = create_entity("info_target")
	if(!is_valid_ent(Ent))
	{
		format(g_Query,511,"Unable to spawn NPC.",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,0)
	}
	
	entity_set_string(Ent,EV_SZ_classname,g_NpcClassname)
	//entity_set_model(Ent,Model)
	entity_set_model(Ent,Model)
	entity_set_origin(Ent,Origin)
	entity_set_size(Ent,Float:{-16.0,-16.0,-36.0},Float:{16.0,16.0,36.0})
	entity_set_int(Ent,EV_INT_solid,SOLID_BBOX)
	entity_set_byte(Ent,EV_BYTE_controller1,125)
	entity_set_byte(Ent,EV_BYTE_controller2,125)
	entity_set_byte(Ent,EV_BYTE_controller3,125)
	entity_set_byte(Ent,EV_BYTE_controller4,125)
	entity_set_int(Ent,EV_INT_sequence,1)
	entity_set_float(Ent,EV_FL_framerate,1.0)
	entity_set_vector(Ent,EV_VEC_angles,Angles)
	entity_set_int(Ent,EV_INT_iuser3,Plugin)
	entity_set_string(Ent,EV_SZ_noise,Handler)
	entity_set_string(Ent,EV_SZ_noise1,Name)
	
	drop_to_floor(Ent)
	
	return Ent
}

public _DPRP_IsNpc(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Classname[33],Ent = get_param(1)
	if(!is_valid_ent(Ent))
	{
		format(g_Query,511,"Invalid entity: %d",Ent)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	entity_get_string(Ent,EV_SZ_classname,Classname,32)
	
	if(equal(Classname,g_NpcClassname))
		return SUCCEEDED
	
	return FAILED
}

public _DPRP_AddCommand(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new Array = array_create()
	
	array_set_int(g_CommandArray,++g_CommandNum,Array)
	
	get_string(1,g_Query,511)
	array_set_string(Array,1,g_Query)
		
	get_string(2,g_Query,511)
	array_set_string(Array,2,g_Query)
	
	return SUCCEEDED
}

/*public _DPRP_GetUserItemId(Plugin,Params)
{
	if(Params != 2)
		return FAILED
		
	new id = get_param(1),Column = get_param(2)
	
	if(Column > g_UserItemNum[id] || !is_user_connected(id))
		return FAILED
		
	new Array =
	
	return array_isfilled(array_get_int(g_UserItemArray[id],Column),) 
}*/

public _DPRP_GetUserItemNum(Plugin,Params)
{
	if(Params != 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
		
	new id = get_param(1),ItemId = get_param(2) - 1
	
	if(!is_user_connected(id))
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(!UTIL_DPRP_ValidItemId(ItemId))
	{
		format(g_Query,511,"Invalid item id: %d",ItemId)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return UTIL_DPRP_GetUserItemNum(id,ItemId)
}

public _DPRP_GetUserItems(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1)
	if(is_user_connected(id))
		return g_UserItemNum[id]
	else
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return FAILED
}

public _DPRP_SetUserItemNum(Plugin,Params)
{
	if(Params != 3)
	{
		format(g_Query,511,"Parameters do not match. Expected: 3, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1),ItemId = get_param(2) - 1,ItemNum = get_param(3)/*,Cell = -1,Cache[2][MAX_USER_ITEMS]*/
	
	if(ItemNum < 0)
	{
		format(g_Query,511,"Invalid item number, must be more than 0. Num: %d",ItemNum)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(!UTIL_DPRP_ValidItemId(ItemId))
	{
		format(g_Query,511,"Invalid item id: %d",ItemId)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	return UTIL_DPRP_SetUserItemNum(id,ItemId,ItemNum)
	
	/*for(new Count;Count < MAX_USER_ITEMS;Count++)
		if(g_UserItemIds[id][Count] == ItemId)
		{
			Cell = Count
			break
		}
	
	if(Cell < 0)
		for(new Count;Count < MAX_USER_ITEMS;Count++)
			if(!g_UserItemIds[id][Count] || !g_UserItems[id][Count])
			{
				Cell = Count
				break
			}
	
	// if it's STILL less than 0
	if(Cell < 0)
	{
		log_amx("ERROR: User has max items!")
		return FAILED
	}
	
	g_UserItems[id][Cell] = Num
	g_UserItemIds[id][Cell] = ItemId
	
	Num = 0
	for(new Count;Count < MAX_USER_ITEMS;Count++)
		if(g_UserItems[id][Count] && g_UserItemIds[id][Count])
		{
			Cache[0][Num] = g_UserItems[id][Count]
			Cache[1][Num++] = g_UserItemIds[id][Count]
		}
	
	for(new Count;Count < MAX_USER_ITEMS;Count++)
		if(Count < Num)
		{
			g_UserItems[id][Count] = Cache[0][Count]
			g_UserItemIds[id][Count] = Cache[1][Count]
		}
		else
		{
			g_UserItems[id][Count] = 0
			g_UserItemIds[id][Count] = 0
		}
	
	return SUCCEEDED*/
}

public _DPRP_ItemDone(Plugin,Params)
{
	if(Params != 1)
	{
		format(g_Query,511,"Parameters do not match. Expected: 1, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	new id = get_param(1)
	if(!is_user_connected(id))
	{
		format(g_Query,511,"User not connected: %d",id)
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,Plugin)
	}
	
	if(g_ItemUse[id] == Plugin)
		g_ItemUse[id] = 0
		
	return SUCCEEDED
}

public _DPRP_ThrowError(Plugin,Params)
{
	if(Params < 2)
	{
		format(g_Query,511,"Parameters do not match. Expected: 2 or more, Found: %d",Params)
		return UTIL_DPRP_ThrowError(AMX_ERR_PARAMS,0,g_Query,Plugin)
	}
	
	get_string(2,g_Query,511)
	new Mode = get_param(1)
	
	vformat(g_Query,511,g_Query,3)
	
	UTIL_DPRP_ThrowError(0,Mode,g_Query,Plugin)
	
	return SUCCEEDED
}
	
public client_putinserver(id)
{
	g_Joined[id] = false
	g_GotInfo[id] = false
	
	g_ItemUse[id] = 0
	
	new Authid[36],Data[1]
	get_user_authid(id,Authid,35)
	Data[0] = id
	
	format(g_Query,511,"SELECT * FROM %s WHERE authid='%s'",g_UserTable,Authid)
	SQL_ThreadQuery(g_SqlHandle,"FetchClientData",g_Query,Data,1)
	
	format(g_Query,511,"SELECT * FROM %s WHERE authidname LIKE '%s|%%'",g_ItemsTable,Authid)
	SQL_ThreadQuery(g_SqlHandle,"FetchClientItems",g_Query,Data,1)
	
	format(g_Query,511,"SELECT * FROM %s WHERE authid='%s'",g_KeysTable,Authid)
	SQL_ThreadQuery(g_SqlHandle,"FetchClientKeys",g_Query,Data,1)
}

public FetchClientData(FailState,Handle:Query,Error[],Errcode,Data[],DataSize) 
{
	if(FailState == TQUERY_CONNECT_FAILED)
	{
		format(g_Query,511,"Could not connect to SQL database.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	else if(FailState == TQUERY_QUERY_FAILED)
	{
		format(g_Query,511,"Internal error: consult developer.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	
	if(Errcode)
	{
		format(g_Query,511,"Error on query: %s",Error)
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
		
	new id = Data[0]
	
	if(SQL_NumResults(Query) < 1)
	{
		new Authid[36],StartMoney = get_pcvar_num(p_StartMoney)
		get_user_authid(id,Authid,35)
		
		format(g_Query,511,"INSERT INTO %s VALUES('%s','Unemployed','%d','0','0','','')",g_UserTable,Authid,StartMoney)
		SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
		
		new Results[1]
		DPRP_FindJobId("Unemployed",Results,1)
		
		Results[0] -= 1
		
		if(!UTIL_DPRP_ValidJobId(Results[0]))
			Results[0] = DPRP_AddJob("Unemployed",5,0) - 1
		
		g_Money[id] = StartMoney
		g_Hunger[id] = 0
		g_BankMoney[id] = 0
		g_JobId[id] = Results[0]
		g_Access[id] = array_get_int(array_get_int(g_JobsArray,Results[0]),3)
		g_AccessCache[id] = 0
		g_JobRight[id] = 0
		g_Salary[id] = array_get_int(array_get_int(g_JobsArray,Results[0]),2)
		
		array_clear(g_UserItemArray[id])
		
		return PLUGIN_CONTINUE
	}
	
	// terrible way of doing it (like 2000 cells in total) but whatever
	new Temp[512]//,Exploded[MAX_USER_ITEMS][10],Left[5],Right[5]
	//SQL_ReadResult(Query,3,Temp,511)
	
	g_BankMoney[id] = SQL_ReadResult(Query,1)
	g_Money[id] = SQL_ReadResult(Query,2)
	
	/*new Num = ExplodeString(Exploded,MAX_USER_ITEMS,Temp,9,' '),Array
	
	for(new Count;Count <= Num;Count++)
	{
		strtok(Exploded[Count],Left,4,Right,4,'|',1)
		
		Array = array_create()
		array_set_int(g_UserItemArray[id],++g_UserItemNum[id],Array)
		array_set_int(Array,1,str_to_num(Left))
		array_set_int(Array,2,str_to_num(Right))
	}*/
	
	new Results[2]
	SQL_ReadResult(Query,3,Temp,511)
	DPRP_FindJobId(Temp,Results,2)
	
	g_JobId[id] = Results[0] - 1
	
	if((Results[0] && Results[1]) || !Results[0])
	{
		g_BadJob[id] = 1
		
		DPRP_FindJobId("Unemployed",Results,1)
		if(!UTIL_DPRP_ValidJobId(Results[0] - 1))
			Results[0] = DPRP_AddJob("Unemployed",5,0) - 1
			
		g_JobId[id] = Results[0] - 1
		g_Salary[id] = 5
	}
	else if(UTIL_DPRP_ValidJobId(g_JobId[id]))
		g_BadJob[id] = 0
	else
	{
		g_BadJob[id] = 1
		
		DPRP_FindJobId("Unemployed",Results,1)
		if(!UTIL_DPRP_ValidJobId(Results[0] - 1))
			Results[0] = DPRP_AddJob("Unemployed",5,0) - 1
			
		g_JobId[id] = Results[0] - 1
		g_Salary[id] = 5
	}
	
	g_Hunger[id] = SQL_ReadResult(Query,4)	
	SQL_ReadResult(Query,5,Temp,511)
	g_Access[id] = DPRP_AccessToInt(Temp)
	g_AccessCache[id] = g_Access[id]

	g_Salary[id] = array_get_int(array_get_int(g_JobsArray,g_JobId[id]),2)
	g_Access[id] |= array_get_int(array_get_int(g_JobsArray,g_JobId[id]),3)
		
	SQL_ReadResult(Query,6,Temp,511)
	g_JobRight[id] = DPRP_AccessToInt(Temp)
	
	g_GotInfo[id] = true
	
	return PLUGIN_CONTINUE
}

public FetchClientItems(FailState,Handle:Query,Error[],Errcode,Data[],DataSize) 
{
	if(FailState == TQUERY_CONNECT_FAILED)
	{
		format(g_Query,511,"Could not connect to SQL database.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	else if(FailState == TQUERY_QUERY_FAILED)
	{
		format(g_Query,511,"Internal error: consult developer.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	
	if(Errcode)
	{
		format(g_Query,511,"Error on query: %s",Error)
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
		
	new id = Data[0],Temp[2][36],ItemId
	
	array_clear(g_UserItemArray[id])
	
	while(SQL_MoreResults(Query))
	{
		SQL_ReadResult(Query,0,g_Query,511)
		strtok(g_Query,Temp[0],35,Temp[1],35,'|',1)
		
		ItemId = UTIL_DPRP_FindItemId(Temp[1])
		
		if(!UTIL_DPRP_ValidItemId(ItemId))
		{			
			SQL_NextRow(Query)
			continue
		}
		
		array_set_int(g_UserItemArray[id],ItemId,SQL_ReadResult(Query,1))
		
		SQL_NextRow(Query)
	}
	
	return PLUGIN_CONTINUE
}

public FetchClientKeys(FailState,Handle:Query,Error[],Errcode,Data[],DataSize) 
{
	if(FailState == TQUERY_CONNECT_FAILED)
	{
		format(g_Query,511,"Could not connect to SQL database.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	else if(FailState == TQUERY_QUERY_FAILED)
	{
		format(g_Query,511,"Internal error: consult developer.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	
	if(Errcode)
	{
		format(g_Query,511,"Error on query: %s",Error)
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
		
	new id = Data[0],MapName[33],CurrentMap[33],InternalName[33],Property
	get_mapname(CurrentMap,32)
	while(SQL_MoreResults(Query))
	{
		SQL_ReadResult(Query,2,MapName,32)
		if(!equali(MapName,CurrentMap))
		{
			SQL_NextRow(Query)
			continue
		}
		
		SQL_ReadResult(Query,1,InternalName,32)
		
		Property = UTIL_DPRP_MatchProperty(InternalName)
		if(Property == -1)
			continue
		
		array_set_int(array_get_int(g_PropertyArray,Property),8,array_get_int(array_get_int(g_PropertyArray,Property),8)|(1<<id))
		
		SQL_NextRow(Query)
	}
	
	return PLUGIN_CONTINUE
}

/*
Handle:SqlConnect()
{
	static Errcode,Error[256]
	new Handle:SqlConnection = SQL_Connect(g_SqlHandle,Errcode,Error,255)
	
	if(SqlConnection == Empty_Handle)
	{
		log_amx(Error)
		g_SqlOk = false		
		
		return Handle:0
	}
	
	return SqlConnection
}
*/

public IgnoreHandle(FailState,Handle:Query,Error[],Errcode,Data[],DataSize) 
{
	if(FailState == TQUERY_CONNECT_FAILED)
	{
		format(g_Query,511,"Could not connect to SQL database.")
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	else if(FailState == TQUERY_QUERY_FAILED)
	{
		SQL_GetQueryString(Query,g_Query,511)
		log_amx("Query: %s",g_Query)
		
		SQL_QueryError(Query,g_Query,511)
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}
	
	if(Errcode)
	{
		format(g_Query,511,"Error on query: %s",Error)
		return UTIL_DPRP_ThrowError(0,1,g_Query,0)
	}	
	
	return PLUGIN_CONTINUE
}

public ShowHud()
{
	g_HudPending = true
	
	new StartTime = 600
		
	g_Time -= 10
	
	// Time is actually in like hundreds
	if(g_Time <= 0)
		g_Time = StartTime
	
	new Players[32],Playersnum,Player,Forward = CreateMultiForward("DPRP_HudDisplay",ET_IGNORE,FP_CELL),Return/*,Pos*/,Retn,Fwd,Title[256],Hostname[128],JobName[33]
	if(!Forward)
		return
		
	get_players(Players,Playersnum)
	
	for(new Count2;Count2 < HUD_NUM;Count2++)
	{
		set_hudmessage(get_pcvar_num(p_HudR[Count2]),get_pcvar_num(p_HudG[Count2]),get_pcvar_num(p_HudB[Count2]),get_pcvar_float(p_HudX[Count2]),get_pcvar_float(p_HudY[Count2]),0,0.0,99.9,0.0,0.0,-1)
		if(!Count2)
		{
			get_pcvar_string(p_HudTitle,Title,255)
			get_pcvar_string(p_Hostname,Hostname,127)
			
			replace_all(Title,255,"#hostname#",Hostname)
			replace_all(Title,255,"\n","^n")
		}
		
		for(new Count;Count < Playersnum;Count++)
		{				
			Player = Players[Count]
			
			if(!is_user_connected(Player) || !is_user_alive(Player) || is_user_bot(Player) || !ExecuteForward(Forward,Return,Player))
				continue
				
			// I don't like adding a native call, but we can't really do this otherwise easily.
			//if(!DPRP_GetJobName(g_JobIds[Player],JobName,32))
				//format(JobName,32,"ERROR, consult admin")
			
			if(g_Time == StartTime && !Count2)
			{
				Fwd = CreateMultiForward("DPRP_Salary",ET_STOP2,FP_CELL)
				if(Fwd < 0 || !ExecuteForward(Fwd,Retn,Player))
					continue
				
				if(!Retn)
					g_BankMoney[Player] += g_Salary[Player]
				
				DestroyForward(Fwd)
			}
			
			g_Hunger[Player] += random_num(0,1)
			if(g_Hunger[Player] > 1000)
				user_kill(Player)
			
			if(UTIL_DPRP_ValidJobId(g_JobId[Player]))
				array_get_string(array_get_int(g_JobsArray,g_JobId[Player]),1,JobName,32)
				
			/*Pos += */
			if(!Count2)
				format(g_Query,511,"%s^n______________^n^nPayday: 	%dm^nSalary: 	$%d/h^nWallet: 	$%d^nBank: 	$%d^nJob: 	%s^nHunger: 	%d%%^n",Title,g_Time / 10,g_Salary[Player],g_Money[Player],g_BankMoney[Player],JobName,g_Hunger[Player] / 10)	
			else
				format(g_Query,511,"%s",g_HudNum[Player][Count2] ? "______________^n^n" : "")
			
			for(new Count3;Count3 < g_HudNum[Player][Count2] && Count3 < MAX_HUD_ITEMS;Count3++)
			{
				add(g_Query,511,g_HudItems[Player + 32 * Count2][Count3])
				add(g_Query,511,"^n")
				
				//Pos += format(g_Query[Pos],511-Pos-1,"%s^n",g_HudItems[Player][Count2])
				g_HudItems[Player + 32 * Count2][Count3][0] = 0
			}
			
			g_HudNum[Player][Count2] = 0
			
			ShowSyncHudMsg(Player,g_HudObjects[Count2],"%s",g_Query)
		}
	}
	
	DestroyForward(Forward)
	
	get_pcvar_string(p_Lights,g_Query,511)
	set_lights(g_Query)
	
	g_HudPending = false
}

public EventDeathMsg()
{
	new id = read_data(2),Message[33]
	
	g_Hunger[id] = 0
	
	if(g_EdekaRobber == id)
	{
		g_EdekaRobber = 0
		Message = "Edeka"
	}
	else if(g_DinerRobber == id)
	{
		g_DinerRobber = 0
		Message = "Diner"
	}
	else if(g_BankRobber == id)
	{
		g_BankRobber = 0
		Message = "Bank"
	}
	
	if(Message[0])
	{
		new Names[2][33],Killer = read_data(1),KillerMsg[64]
		if(Killer && Killer != id)
		{
			get_user_name(Killer,Names[1],32)
			format(KillerMsg,63,"by %s",Names[1])
		}
		
		new Message[128]
		format(Message,127,"#name# has been stopped robbing the %s^n%s",Names[0],Message,KillerMsg)
		
		EndRob(id,Message)
	}
	
	if(get_pcvar_num(p_WalletDeath))
		g_Money[id] = 0
}

public EventResetHUD(id)
	set_task(1.0,"Welcome",id)

public Welcome(id)
	if(is_user_alive(id))
	{
		if(!g_Joined[id])
		{
			client_print(id,print_chat,"[DPRP] This server is running Deep Purple RP by Doug ^"Hawk552^" Karlmann.")
			client_print(id,print_chat,"[DPRP] To get started, say ^"/help^" or type ^"dprp_help^" in your console.")
			
			g_Joined[id] = true
		}
		
		if(g_BadJob[id])
		{
			client_print(id,print_chat,"[DPRP] Notice: Your job no longer exists. Please contact an administrator.")
			client_print(id,print_chat,"[DPRP] You have been temporarily set back to Unemployed.")
			
			g_BadJob[id] = 0
		}
	}
	
public CmdJobList(id)
{
	new Arg[33]
	read_argv(1,Arg,32)
	
	new Start = str_to_num(Arg),Items = get_pcvar_num(p_ItemsPerPage),Num,Access[JOB_ACCESSES + 1],Name[33]
	
	if(Start >= g_JobsNum || Start < 0)
	{
		client_print(id,print_console,"No jobs to display at this area.")
		return PLUGIN_HANDLED
	}
	
	client_print(id,print_console,"DPRP Jobs List (Starting at #%d)",Start)
	client_print(id,print_console,"NUMBER   JOBID   NAME   SALARY   ACCESS")
	
	for(new Count = Start;Count < Start + Items;Count++)
	{
		if(Count >= g_JobsNum)
			break
		
		DPRP_IntToAccess(array_get_int(array_get_int(g_JobsArray,Count),3),Access,JOB_ACCESSES)
		array_get_string(array_get_int(g_JobsArray,Count),1,Name,32)
		
		client_print(id,print_console,"#%d   %d   %s   $%d   %s",++Num,Count + 1,Name,array_get_int(array_get_int(g_JobsArray,Count),2),Access)
	}
	
	if(Start + Items < g_JobsNum)
		client_print(id,print_console,"Type ^"dprp_joblist %d^" to view next jobs.",Start + Items)
	
	return PLUGIN_HANDLED
}

public CmdItemList(id)
{
	new Arg[33]
	read_argv(1,Arg,32)
	
	new Start = str_to_num(Arg),Items = get_pcvar_num(p_ItemsPerPage)
	
	if(Start >= g_ItemsNum || Start < 0)
	{
		client_print(id,print_console,"No jobs to display at this area.")
		return PLUGIN_HANDLED
	}
	
	client_print(id,print_console,"DPRP Items List (Starting at #%d)",Start)
	client_print(id,print_console,"NUMBER   ITEMID   NAME   DISPOSABLE   DESCRIPTION")
	
	new Name[33],Description[64],Array
	
	for(new Count = Start;Count < Start + Items;Count++)
	{
		if(Count >= g_ItemsNum)
			break
		
		Array = array_get_int(g_ItemsArray,Count)
		
		array_get_string(Array,1,Name,32)
		array_get_string(Array,4,Description,63)
		
		client_print(id,print_console,"#%d   %s   %s   %s",Count + 1,Name,array_get_int(Array,5) ? "Yes" : "No",Description)
	}
	
	if(Start + Items < g_ItemsNum)
		client_print(id,print_console,"Type ^"dprp_itemlist %d^" to view next items.",Start + Items)
	
	return PLUGIN_HANDLED
}

ItemUse(id,ItemId,UseUp)
{
	new Handler[33]
	
	g_ItemUse[id] = array_get_int(array_get_int(g_ItemsArray,ItemId),2)
	array_get_string(array_get_int(g_ItemsArray,ItemId),3,Handler,32)
	
	new Forward = CreateOneForward(g_ItemUse[id],Handler,FP_CELL,FP_CELL),Return
	if(Forward < 0)
	{
		format(g_Query,511,"Function ^"%s^" does not exist in plugin %d.",Handler,g_ItemUse[id])
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,0)
	}
	
	if(!ExecuteForward(Forward,Return,id,ItemId + 1))
	{
		format(g_Query,511,"Function ^"%s^" does not exist in plugin %d.",Handler,g_ItemUse[id])
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,0)
	}
	
	// if disposable
	if(UseUp && array_get_int(array_get_int(g_ItemsArray,ItemId),5))
		UTIL_DPRP_SetUserItemNum(id,ItemId,UTIL_DPRP_GetUserItemNum(id,ItemId) - 1)
	
	DestroyForward(Forward)
	
	return SUCCEEDED
}

EndRob(id,reason[])
{
	if(g_EdekaRobber == id)
		g_EdekaRobber = 0
	else if(g_DinerRobber == id)
		g_DinerRobber = 0
	else if(g_BankRobber == id)
		g_BankRobber = 0
	else
		return FAILED
	
	set_rendering(id,kRenderFxNone,255,255,255,kRenderNormal,16)
	
	new Name[33],Msg[256] 
	copy(Msg,255,reason)
	get_user_name(id,Name,32)
	
	replace_all(Msg,255,"#name#",Name)
	
	set_hudmessage(255,255,0,-1.0,0.35,0,0.0,8.0,0.0,0.0,-1)
	show_hudmessage(0,"%s",Msg)
	
	new Forward = CreateMultiForward("DPRP_RobEnd",ET_IGNORE,FP_CELL,FP_STRING),Return
	if(Forward < 0)
	{
		format(g_Query,511,"Error calling DPRP_RobEnd forward.")
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,0)
	}
	
	if(!ExecuteForward(Forward,Return,id,Msg))
	{
		format(g_Query,511,"Error calling DPRP_RobEnd forward.")
		return UTIL_DPRP_ThrowError(AMX_ERR_NATIVE,0,g_Query,0)
	}
	
	DestroyForward(Forward)
	
	return SUCCEEDED
}

UTIL_DPRP_ValidProperty(Property)
{
	if(Property >= 0 && Property < g_PropertyNum)
		return SUCCEEDED
	
	return FAILED
}

UTIL_DPRP_ValidDoor(Door)
{
	if(Door >= 0 && Door < g_DoorNum)
		return SUCCEEDED
	
	return FAILED
}

UTIL_DPRP_GetProperty(Targetname[] = "",EntID = 0)
{
	static PropertyTargetname[33],InternalName[64]
	
	for(new Count;Count < g_DoorNum;Count++)
	{
		if(array_isfilled(array_get_int(g_DoorArray,Count),0))
			array_get_string(array_get_int(g_DoorArray,Count),0,PropertyTargetname,32)
		if((equali(PropertyTargetname,Targetname) && Targetname[0]) || (array_isfilled(array_get_int(g_DoorArray,Count),1) && EntID && EntID == array_get_int(array_get_int(g_DoorArray,Count),1)))
		{
			array_get_string(array_get_int(g_DoorArray,Count),2,InternalName,63)
			return UTIL_DPRP_MatchProperty(InternalName)
		}
	}
	
	return -1
}

UTIL_DPRP_MatchProperty(InternalName[])
{
	static CurName[64]
	
	for(new Count;Count < g_PropertyNum;Count++)
	{
		array_get_string(array_get_int(g_PropertyArray,Count),0,CurName,63)
		if(equali(CurName,InternalName))
			return Count
	}
	
	return -1
}

UTIL_DPRP_FindItemId(ItemName[])
{
	new Name[33]
	for(new Count;Count < g_ItemsNum;Count++)
	{
		array_get_string(array_get_int(g_ItemsArray,Count),1,Name,32)
		
		if(equali(Name,ItemName))
			return Count
	}
	
	return -1
}

UTIL_DPRP_SetUserItemNum(id,ItemId,Num)
{
	if(UTIL_DPRP_ValidItemId(ItemId))
		Num ? array_set_int(g_UserItemArray[id],ItemId,Num) : array_delete(g_UserItemArray[id],ItemId)
	
	if(!Num)
	{
		new Name[33],Authid[36]
		UTIL_DPRP_GetItemName(ItemId,Name,32)
		
		get_user_authid(id,Authid,35)
		
		format(g_Query,511,"DELETE FROM %s WHERE authidname='%s|%s'",g_ItemsTable,Authid,Name)
		SQL_ThreadQuery(g_SqlHandle,"IgnoreHandle",g_Query)
	}
	
	return 1
}

UTIL_DPRP_GetUserItemNum(id,ItemId)
	return array_isfilled(g_UserItemArray[id],ItemId) ? array_get_int(g_UserItemArray[id],ItemId) : 0
		

UTIL_DPRP_GetItemName(ItemId,ItemName[],Len)
{
	if(!UTIL_DPRP_ValidItemId(ItemId))
		return FAILED
	
	array_get_string(array_get_int(g_ItemsArray,ItemId),1,ItemName,Len)
	
	/*new Array
	for(new Count;Count < g_ItemsNum;Count++)
	{
		Array = array_get_int(g_ItemsArray,Count + 1)
		
		if(ItemId == array_get_int(Array,2))
		{
			array_get_string(Array,1,ItemName,Len)
			return SUCCEEDED
		}
	}*/
	
	//return FAILED
	
	return SUCCEEDED
}

UTIL_DPRP_ValidItemId(ItemId)
{
	if(ItemId < g_ItemsNum && ItemId >= 0)
		return SUCCEEDED
	
	return FAILED
}

UTIL_DPRP_ValidJobId(JobId)
{
	if(JobId < g_JobsNum && JobId >= 0)
		return SUCCEEDED
	
	return FAILED
}

UTIL_DPRP_ThrowError(Error,Fatal,Message[],Plugin)
{	
	if(Plugin)
	{
		new Name[64],Filename[64],Temp[2]
	
		get_plugin(Plugin,Filename,63,Name,63,Temp,1,Temp,1,Temp,1)
		
		if(Error)
			log_error(Error,"[DPRP] [PLUGIN: %s - %s] %s",Name,Filename,Message)
		else
			log_amx("[DPRP] [PLUGIN: %s - %s] %s",Name,Filename,Message)
	}
	else
		if(Error)
			log_error(Error,"[DPRP] [PLUGIN: CORE] %s",Message)
		else
			log_amx("[DPRP] [PLUGIN: CORE] %s",Message)
		
	if(Fatal)
	{
		new Forward = CreateMultiForward("DPRP_Error",ET_IGNORE,FP_STRING),Return
		if(Forward < 0 || !ExecuteForward(Forward,Return,Message))
			return SUCCEEDED
		
		DestroyForward(Forward)
		
		pause("d")
	}
	
	return FAILED
}

UTIL_DPRP_ClientPrint(id,Message[],{Float,Sql,Result,_}:...)
{
	vformat(g_Query,511,Message,3)
	
	switch(get_pcvar_num(p_AuxType))
	{
		case 1 :
			client_print(id,print_center,"%s",g_Query)
		case 2 :
		{
			set_hudmessage(get_pcvar_num(p_AuxR),get_pcvar_num(p_AuxG),get_pcvar_num(p_AuxB),get_pcvar_float(p_AuxX),get_pcvar_float(p_AuxY),0,0.0,2.0,0.0,0.0,-1)
			ShowSyncHudMsg(id,g_HudObj,"%s",g_Query)
		}
	}
}
